syntax = "proto3";

package envoy.config.common.dynamic_forward_proxy.v2alpha;

import "envoy/api/v2/cluster.proto";

import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "udpa/annotations/migrate.proto";
import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.config.common.dynamic_forward_proxy.v2alpha";
option java_outer_classname = "DnsCacheProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/common/dynamic_forward_proxy/v2alpha";
option (udpa.annotations.file_migrate).move_to_package =
    "envoy.extensions.common.dynamic_forward_proxy.v3";
option (udpa.annotations.file_status).package_version_status = FROZEN;

// [#protodoc-title: Dynamic forward proxy common configuration]

// Configuration for the dynamic forward proxy DNS cache. See the :ref:`architecture overview
// <arch_overview_http_dynamic_forward_proxy>` for more information.
// [#next-free-field: 7]
message DnsCacheConfig {
  // The name of the cache. Multiple named caches allow independent dynamic forward proxy
  // configurations to operate within a single Envoy process using different configurations. All
  // configurations with the same name *must* otherwise have the same settings when referenced
  // from different configuration components. Configuration will fail to load if this is not
  // the case.
  string name = 1 [(validate.rules).string = {min_bytes: 1}];

  // The DNS lookup family to use during resolution.
  //
  // [#comment:TODO(mattklein123): Figure out how to support IPv4/IPv6 "happy eyeballs" mode. The
  // way this might work is a new lookup family which returns both IPv4 and IPv6 addresses, and
  // then configures a host to have a primary and fall back address. With this, we could very
  // likely build a "happy eyeballs" connection pool which would race the primary / fall back
  // address and return the one that wins. This same method could potentially also be used for
  // QUIC to TCP fall back.]
  api.v2.Cluster.DnsLookupFamily dns_lookup_family = 2
      [(validate.rules).enum = {defined_only: true}];

  // The DNS refresh rate for currently cached DNS hosts. If not specified defaults to 60s.
  //
  // .. note:
  //
  //  The returned DNS TTL is not currently used to alter the refresh rate. This feature will be
  //  added in a future change.
  //
  // .. note:
  //
  // The refresh rate is rounded to the closest millisecond, and must be at least 1ms.
  google.protobuf.Duration dns_refresh_rate = 3
      [(validate.rules).duration = {gte {nanos: 1000000}}];

  // The TTL for hosts that are unused. Hosts that have not been used in the configured time
  // interval will be purged. If not specified defaults to 5m.
  //
  // .. note:
  //
  //   The TTL is only checked at the time of DNS refresh, as specified by *dns_refresh_rate*. This
  //   means that if the configured TTL is shorter than the refresh rate the host may not be removed
  //   immediately.
  //
  //  .. note:
  //
  //   The TTL has no relation to DNS TTL and is only used to control Envoy's resource usage.
  google.protobuf.Duration host_ttl = 4 [(validate.rules).duration = {gt {}}];

  // The maximum number of hosts that the cache will hold. If not specified defaults to 1024.
  //
  // .. note:
  //
  //   The implementation is approximate and enforced independently on each worker thread, thus
  //   it is possible for the maximum hosts in the cache to go slightly above the configured
  //   value depending on timing. This is similar to how other circuit breakers work.
  google.protobuf.UInt32Value max_hosts = 5 [(validate.rules).uint32 = {gt: 0}];

  // If the DNS failure refresh rate is specified,
  // this is used as the cache's DNS refresh rate when DNS requests are failing. If this setting is
  // not specified, the failure refresh rate defaults to the dns_refresh_rate.
  api.v2.Cluster.RefreshRate dns_failure_refresh_rate = 6;
}
