LCOV - code coverage report
Current view: top level - source/extensions/common/dynamic_forward_proxy - dns_cache_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 0 55 0.0 %
Date: 2024-01-05 06:35:25 Functions: 0 16 0.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "envoy/common/backoff_strategy.h"
       4             : #include "envoy/common/key_value_store.h"
       5             : #include "envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.pb.h"
       6             : #include "envoy/http/filter.h"
       7             : #include "envoy/network/dns.h"
       8             : #include "envoy/server/factory_context.h"
       9             : #include "envoy/thread_local/thread_local.h"
      10             : 
      11             : #include "source/common/common/cleanup.h"
      12             : #include "source/extensions/common/dynamic_forward_proxy/dns_cache.h"
      13             : #include "source/extensions/common/dynamic_forward_proxy/dns_cache_resource_manager.h"
      14             : #include "source/server/generic_factory_context.h"
      15             : 
      16             : #include "absl/container/flat_hash_map.h"
      17             : 
      18             : namespace Envoy {
      19             : namespace Extensions {
      20             : namespace Common {
      21             : namespace DynamicForwardProxy {
      22             : 
      23             : /**
      24             :  * All DNS cache stats. @see stats_macros.h
      25             :  */
      26             : #define ALL_DNS_CACHE_STATS(COUNTER, GAUGE)                                                        \
      27           0 :   COUNTER(cache_load)                                                                              \
      28           0 :   COUNTER(dns_query_attempt)                                                                       \
      29           0 :   COUNTER(dns_query_failure)                                                                       \
      30           0 :   COUNTER(dns_query_success)                                                                       \
      31           0 :   COUNTER(dns_query_timeout)                                                                       \
      32           0 :   COUNTER(host_added)                                                                              \
      33           0 :   COUNTER(host_address_changed)                                                                    \
      34           0 :   COUNTER(host_overflow)                                                                           \
      35           0 :   COUNTER(host_removed)                                                                            \
      36           0 :   COUNTER(dns_rq_pending_overflow)                                                                 \
      37           0 :   GAUGE(num_hosts, NeverImport)
      38             : 
      39             : /**
      40             :  * Struct definition for all DNS cache stats. @see stats_macros.h
      41             :  */
      42             : struct DnsCacheStats {
      43             :   ALL_DNS_CACHE_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT)
      44             : };
      45             : 
      46             : class DnsCacheImplTest;
      47             : 
      48             : class DnsCacheImpl : public DnsCache, Logger::Loggable<Logger::Id::forward_proxy> {
      49             : public:
      50             :   // Create a DnsCacheImpl or return a failed status;
      51             :   static absl::StatusOr<std::shared_ptr<DnsCacheImpl>> createDnsCacheImpl(
      52             :       Server::Configuration::GenericFactoryContext& context,
      53             :       const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig& config);
      54             : 
      55             :   ~DnsCacheImpl() override;
      56             :   static DnsCacheStats generateDnsCacheStats(Stats::Scope& scope);
      57             :   static Network::DnsResolverSharedPtr selectDnsResolver(
      58             :       const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig& config,
      59             :       Event::Dispatcher& main_thread_dispatcher,
      60             :       Server::Configuration::CommonFactoryContext& context);
      61             : 
      62             :   // DnsCache
      63             :   LoadDnsCacheEntryResult loadDnsCacheEntry(absl::string_view host, uint16_t default_port,
      64             :                                             bool is_proxy_lookup,
      65             :                                             LoadDnsCacheEntryCallbacks& callbacks) override;
      66             :   AddUpdateCallbacksHandlePtr addUpdateCallbacks(UpdateCallbacks& callbacks) override;
      67             :   void iterateHostMap(IterateHostMapCb cb) override;
      68             :   absl::optional<const DnsHostInfoSharedPtr> getHost(absl::string_view host_name) override;
      69             :   Upstream::ResourceAutoIncDecPtr canCreateDnsRequest() override;
      70             :   void forceRefreshHosts() override;
      71             : 
      72             : private:
      73             :   DnsCacheImpl(Server::Configuration::GenericFactoryContext& context,
      74             :                const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig& config);
      75             :   struct LoadDnsCacheEntryHandleImpl
      76             :       : public LoadDnsCacheEntryHandle,
      77             :         RaiiMapOfListElement<std::string, LoadDnsCacheEntryHandleImpl*> {
      78             :     LoadDnsCacheEntryHandleImpl(
      79             :         absl::flat_hash_map<std::string, std::list<LoadDnsCacheEntryHandleImpl*>>& parent,
      80             :         absl::string_view host, LoadDnsCacheEntryCallbacks& callbacks)
      81             :         : RaiiMapOfListElement<std::string, LoadDnsCacheEntryHandleImpl*>(parent, host, this),
      82           0 :           callbacks_(callbacks) {}
      83             : 
      84             :     LoadDnsCacheEntryCallbacks& callbacks_;
      85             :   };
      86             : 
      87             :   class DnsHostInfoImpl;
      88             :   using DnsHostInfoImplSharedPtr = std::shared_ptr<DnsHostInfoImpl>;
      89             : 
      90             :   struct HostMapUpdateInfo {
      91             :     HostMapUpdateInfo(const std::string& host, DnsHostInfoImplSharedPtr info)
      92           0 :         : host_(host), info_(std::move(info)) {}
      93             :     std::string host_;
      94             :     DnsHostInfoImplSharedPtr info_;
      95             :   };
      96             :   using HostMapUpdateInfoSharedPtr = std::shared_ptr<HostMapUpdateInfo>;
      97             : 
      98             :   // Per-thread DNS cache info including pending callbacks.
      99             :   struct ThreadLocalHostInfo : public ThreadLocal::ThreadLocalObject {
     100           0 :     ThreadLocalHostInfo(DnsCacheImpl& parent) : parent_{parent} {}
     101             :     ~ThreadLocalHostInfo() override;
     102             :     void onHostMapUpdate(const HostMapUpdateInfoSharedPtr& resolved_info);
     103             :     absl::flat_hash_map<std::string, std::list<LoadDnsCacheEntryHandleImpl*>> pending_resolutions_;
     104             :     DnsCacheImpl& parent_;
     105             :   };
     106             : 
     107             :   class DnsHostInfoImpl : public DnsHostInfo {
     108             :   public:
     109             :     DnsHostInfoImpl(TimeSource& time_source, absl::string_view resolved_host, bool is_ip_address)
     110             :         : time_source_(time_source), resolved_host_(resolved_host), is_ip_address_(is_ip_address),
     111           0 :           stale_at_time_(time_source.monotonicTime()) {
     112           0 :       touch();
     113           0 :     }
     114             : 
     115             :     // DnsHostInfo
     116           0 :     Network::Address::InstanceConstSharedPtr address() const override {
     117           0 :       absl::ReaderMutexLock lock{&resolve_lock_};
     118           0 :       return address_;
     119           0 :     }
     120             : 
     121           0 :     std::vector<Network::Address::InstanceConstSharedPtr> addressList() const override {
     122           0 :       std::vector<Network::Address::InstanceConstSharedPtr> ret;
     123           0 :       absl::ReaderMutexLock lock{&resolve_lock_};
     124           0 :       ret = address_list_;
     125           0 :       return ret;
     126           0 :     }
     127             : 
     128           0 :     const std::string& resolvedHost() const override { return resolved_host_; }
     129           0 :     bool isIpAddress() const override { return is_ip_address_; }
     130           0 :     void touch() final { last_used_time_ = time_source_.monotonicTime().time_since_epoch(); }
     131           0 :     void updateStale(MonotonicTime resolution_time, std::chrono::seconds ttl) {
     132           0 :       stale_at_time_ = resolution_time + ttl;
     133           0 :     }
     134           0 :     bool isStale() {
     135           0 :       return time_source_.monotonicTime() > static_cast<MonotonicTime>(stale_at_time_);
     136           0 :     }
     137             : 
     138             :     void setAddresses(Network::Address::InstanceConstSharedPtr address,
     139           0 :                       std::vector<Network::Address::InstanceConstSharedPtr>&& list) {
     140           0 :       absl::WriterMutexLock lock{&resolve_lock_};
     141           0 :       if (!(Runtime::runtimeFeatureEnabled(
     142           0 :               "envoy.reloadable_features.dns_cache_set_first_resolve_complete"))) {
     143           0 :         first_resolve_complete_ = true;
     144           0 :       }
     145           0 :       address_ = address;
     146           0 :       address_list_ = std::move(list);
     147           0 :     }
     148             : 
     149           0 :     std::chrono::steady_clock::duration lastUsedTime() const { return last_used_time_.load(); }
     150             : 
     151           0 :     bool firstResolveComplete() const override {
     152           0 :       absl::ReaderMutexLock lock{&resolve_lock_};
     153           0 :       return first_resolve_complete_;
     154           0 :     }
     155             : 
     156           0 :     void setFirstResolveComplete() {
     157           0 :       absl::WriterMutexLock lock{&resolve_lock_};
     158           0 :       first_resolve_complete_ = true;
     159           0 :     }
     160             : 
     161             :   private:
     162             :     friend class DnsCacheImplTest;
     163             :     TimeSource& time_source_;
     164             :     const std::string resolved_host_;
     165             :     const bool is_ip_address_;
     166             :     mutable absl::Mutex resolve_lock_;
     167             :     Network::Address::InstanceConstSharedPtr address_ ABSL_GUARDED_BY(resolve_lock_);
     168             :     std::vector<Network::Address::InstanceConstSharedPtr>
     169             :         address_list_ ABSL_GUARDED_BY(resolve_lock_);
     170             : 
     171             :     // Using std::chrono::steady_clock::duration is required for compilation within an atomic vs.
     172             :     // using MonotonicTime.
     173             :     std::atomic<std::chrono::steady_clock::duration> last_used_time_;
     174             :     std::atomic<MonotonicTime> stale_at_time_;
     175             :     bool first_resolve_complete_ ABSL_GUARDED_BY(resolve_lock_){false};
     176             :   };
     177             : 
     178             :   // Primary host information that accounts for TTL, re-resolution, etc.
     179             :   struct PrimaryHostInfo {
     180             :     PrimaryHostInfo(DnsCacheImpl& parent, absl::string_view host_to_resolve, uint16_t port,
     181             :                     bool is_ip_address, const Event::TimerCb& refresh_timer_cb,
     182             :                     const Event::TimerCb& timeout_timer_cb);
     183             :     ~PrimaryHostInfo();
     184             : 
     185             :     DnsCacheImpl& parent_;
     186             :     const uint16_t port_;
     187             :     const Event::TimerPtr refresh_timer_;
     188             :     const Event::TimerPtr timeout_timer_;
     189             :     const DnsHostInfoImplSharedPtr host_info_;
     190             :     const BackOffStrategyPtr failure_backoff_strategy_;
     191             :     Network::ActiveDnsQuery* active_query_{};
     192             :   };
     193             : 
     194             :   // Hold PrimaryHostInfo by shared_ptr to avoid having to hold the map mutex while updating
     195             :   // individual entries.
     196             :   using PrimaryHostInfoPtr = std::unique_ptr<PrimaryHostInfo>;
     197             : 
     198             :   struct AddUpdateCallbacksHandleImpl : public AddUpdateCallbacksHandle,
     199             :                                         RaiiListElement<AddUpdateCallbacksHandleImpl*> {
     200             :     AddUpdateCallbacksHandleImpl(std::list<AddUpdateCallbacksHandleImpl*>& parent,
     201             :                                  UpdateCallbacks& callbacks)
     202           0 :         : RaiiListElement<AddUpdateCallbacksHandleImpl*>(parent, this), callbacks_(callbacks) {}
     203             : 
     204             :     UpdateCallbacks& callbacks_;
     205             :   };
     206             : 
     207             :   void startCacheLoad(const std::string& host, uint16_t default_port, bool is_proxy_lookup);
     208             : 
     209             :   void startResolve(const std::string& host, PrimaryHostInfo& host_info)
     210             :       ABSL_LOCKS_EXCLUDED(primary_hosts_lock_);
     211             : 
     212             :   void finishResolve(const std::string& host, Network::DnsResolver::ResolutionStatus status,
     213             :                      std::list<Network::DnsResponse>&& response,
     214             :                      absl::optional<MonotonicTime> resolution_time = {},
     215             :                      bool is_proxy_lookup = false);
     216             :   void runAddUpdateCallbacks(const std::string& host, const DnsHostInfoSharedPtr& host_info);
     217             :   void runResolutionCompleteCallbacks(const std::string& host,
     218             :                                       const DnsHostInfoSharedPtr& host_info,
     219             :                                       Network::DnsResolver::ResolutionStatus status);
     220             :   void runRemoveCallbacks(const std::string& host);
     221             :   void notifyThreads(const std::string& host, const DnsHostInfoImplSharedPtr& resolved_info);
     222             :   void onReResolve(const std::string& host);
     223             :   void onResolveTimeout(const std::string& host);
     224             :   PrimaryHostInfo& getPrimaryHost(const std::string& host);
     225             : 
     226             :   void addCacheEntry(const std::string& host,
     227             :                      const Network::Address::InstanceConstSharedPtr& address,
     228             :                      const std::vector<Network::Address::InstanceConstSharedPtr>& address_list,
     229             :                      const std::chrono::seconds ttl);
     230             :   void removeCacheEntry(const std::string& host);
     231             :   void loadCacheEntries(
     232             :       const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig& config);
     233             :   PrimaryHostInfo* createHost(const std::string& host, uint16_t default_port);
     234             :   absl::optional<Network::DnsResponse> parseValue(absl::string_view value,
     235             :                                                   absl::optional<MonotonicTime>& resolution_time);
     236             : 
     237             :   Event::Dispatcher& main_thread_dispatcher_;
     238             :   const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig config_;
     239             :   Random::RandomGenerator& random_generator_;
     240             :   const Network::DnsLookupFamily dns_lookup_family_;
     241             :   const Network::DnsResolverSharedPtr resolver_;
     242             :   ThreadLocal::TypedSlot<ThreadLocalHostInfo> tls_slot_;
     243             :   Stats::ScopeSharedPtr scope_;
     244             :   DnsCacheStats stats_;
     245             :   std::list<AddUpdateCallbacksHandleImpl*> update_callbacks_;
     246             :   absl::Mutex primary_hosts_lock_;
     247             :   absl::flat_hash_map<std::string, PrimaryHostInfoPtr>
     248             :       primary_hosts_ ABSL_GUARDED_BY(primary_hosts_lock_);
     249             :   std::unique_ptr<KeyValueStore> key_value_store_;
     250             :   DnsCacheResourceManagerImpl resource_manager_;
     251             :   const std::chrono::milliseconds refresh_interval_;
     252             :   const std::chrono::milliseconds min_refresh_interval_;
     253             :   const std::chrono::milliseconds timeout_interval_;
     254             :   Filesystem::Instance& file_system_;
     255             :   ProtobufMessage::ValidationVisitor& validation_visitor_;
     256             :   const std::chrono::milliseconds host_ttl_;
     257             :   const uint32_t max_hosts_;
     258             : };
     259             : 
     260             : } // namespace DynamicForwardProxy
     261             : } // namespace Common
     262             : } // namespace Extensions
     263             : } // namespace Envoy

Generated by: LCOV version 1.15