Repository: envoyproxy/envoy
File: api/envoy/extensions/filters/network/tcp_proxy/v3/tcp_proxy.proto (Protocol Buffers)

Code before:
  // before the upstream connection is established.
  //
  // This mode requires ``max_early_data_bytes`` to be set.
  //
  // .. warning::
  //   This mode is not suitable for server-first protocols (e.g., SMTP, MySQL, POP3) where the
  //   server sends the initial greeting. For such protocols, use ``IMMEDIATE`` mode.
  ON_DOWNSTREAM_DATA = 1;

  // Wait for the downstream TLS handshake to complete before establishing the upstream connection.
  // This allows access to the full TLS connection information, including client certificates
  // and negotiated parameters, which can be used for routing decisions or passed as metadata
  // to the upstream.
  //
  // .. note::
  //   This mode is only effective when the downstream connection uses TLS. For non-TLS
  //   connections, it behaves the same as ``IMMEDIATE``.
  ON_DOWNSTREAM_TLS_HANDSHAKE = 2;
}

// Specifies how TLVs specified in ``proxy_protocol_tlvs`` should be merged with
// downstream PROXY protocol TLVs when downstream PROXY protocol state already exists.
enum DownstreamTlvMergePolicy {
  // Keep only the downstream TLVs and ignore the TLVs specified in ``proxy_protocol_tlvs``
  // if downstream PROXY protocol state already exists. Only the downstream TLVs are forwarded
  // to the upstream. This is the default behavior for backward compatibility.
  KEEP_DOWNSTREAM_ONLY = 0;

  // Override downstream TLVs that have the same type as TLVs specified in
  // ``proxy_protocol_tlvs``. TLVs with non-conflicting types from both sources are preserved.
  // This allows adding new TLV values or overriding specific downstream TLV values while
  // preserving other downstream TLVs.
  //
  // .. note::
  //   If multiple TLVs with the same type exist in the downstream state, all of them are
  //   overridden by the tcp_proxy TLVs of that type.
  OVERRIDE_DOWNSTREAM_TLVS_BY_TYPE = 1;

  // Append the TLVs specified in ``proxy_protocol_tlvs`` to the downstream TLVs.
  // This preserves all downstream TLVs and adds the tcp_proxy TLVs to the end.
  // The PROXY protocol v2 specification allows multiple TLVs with the same type,
  // so this mode preserves all TLVs from both sources.
  APPEND_TO_DOWNSTREAM_TLVS = 2;
}

// [#next-free-field: 24]
message TcpProxy {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.tcp_proxy.v2.TcpProxy";

  // Allows specification of multiple upstream clusters along with weights indicating the percentage of

Review comment (suggestion):
But if there is no downstream PROXY protocol, then the configured TLVs are used instead. Please document/clarify this behavior. 

Code after:
  // before the upstream connection is established.
  //
  // This mode requires ``max_early_data_bytes`` to be set.
  //
  // .. warning::
  //   This mode is not suitable for server-first protocols (e.g., SMTP, MySQL, POP3) where the
  //   server sends the initial greeting. For such protocols, use ``IMMEDIATE`` mode.
  ON_DOWNSTREAM_DATA = 1;

  // Wait for the downstream TLS handshake to complete before establishing the upstream connection.
  // This allows access to the full TLS connection information, including client certificates
  // and negotiated parameters, which can be used for routing decisions or passed as metadata
  // to the upstream.
  //
  // This mode requires ``max_early_data_bytes`` to be set (can be zero to disable buffering).
  //
  // .. note::
  //   This mode is only effective when the downstream connection uses TLS. For non-TLS
  //   connections, it behaves the same as ``IMMEDIATE``.
  ON_DOWNSTREAM_TLS_HANDSHAKE = 2;
}

// Specifies how TLVs in ``proxy_protocol_tlvs`` are merged with existing PROXY protocol state
// (e.g., downstream TLVs parsed by the proxy_protocol listener filter).
enum ProxyProtocolTlvMergePolicy {
  // Add configured TLVs only if no PROXY protocol state exists (e.g., no downstream TLVs).
  // If state exists, ignore configured TLVs and use only the existing TLVs.
  // This is the default for backward compatibility.
  ADD_IF_ABSENT = 0;

  // Overwrite existing TLVs (e.g., downstream TLVs) by type with configured TLVs.
  // Non-conflicting TLVs from both sources are preserved.
  // If no state exists, add all configured TLVs.
  // Source/destination addresses from existing state are preserved.
  OVERWRITE_BY_TYPE_IF_EXISTS_OR_ADD = 1;

  // Append configured TLVs to existing TLVs (e.g., downstream TLVs), preserving all TLVs
  // from both sources (PROXY protocol v2 allows duplicate types).
  // If no state exists, add all configured TLVs.
  // Source/destination addresses from existing state are preserved.
  APPEND_IF_EXISTS_OR_ADD = 2;
}

// [#next-free-field: 24]
message TcpProxy {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.tcp_proxy.v2.TcpProxy";

  // Allows specification of multiple upstream clusters along with weights indicating the percentage of
  // traffic forwarded to each cluster. The cluster selection is based on these weights.
  message WeightedCluster {