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

Code before:
  // When set to ``false`` (default), the TLVs specified in ``proxy_protocol_tlvs`` are
  // ignored if downstream ``PROXY`` protocol state already exists. In this case, only
  // the downstream TLVs are forwarded to the upstream.
  //
  // **Precedence behavior**:
  //
  // - TLVs specified in ``proxy_protocol_tlvs`` take precedence over downstream TLVs
  //   with the same type. This allows adding or overriding specific TLV values while
  //   preserving other downstream TLVs.
  // - The source/destination addresses from the downstream ``PROXY`` protocol state
  //   are preserved (not modified).
  // - TLVs with types that do not conflict are combined, resulting in a merged set
  //   of TLVs from both sources.
  //
  // .. note::
  //   This field only takes effect when downstream ``PROXY`` protocol state exists.
  //   If the TCP proxy filter is creating new ``PROXY`` protocol state, this field
  //   has no effect and the TLVs specified in ``proxy_protocol_tlvs`` are always
  //   included.
  //
  // .. note::
  //   To ensure the merged TLVs are allowed in the upstream ``PROXY`` protocol header,
  //   you must also configure passthrough TLVs on the upstream proxy protocol transport.
  //   See :ref:`core.v3.ProxyProtocolConfig.pass_through_tlvs <envoy_v3_api_field_config.core.v3.ProxyProtocolConfig.pass_through_tlvs>`
  //   for details.
  bool merge_with_downstream_tlvs = 23;

  // Specifies when to establish the upstream connection.
  //
  // When not specified, defaults to ``IMMEDIATE`` for backward compatibility.
  //
  // .. attention::
  //   Server-first protocols (e.g., SMTP, MySQL, POP3) require ``IMMEDIATE`` mode.
  UpstreamConnectMode upstream_connect_mode = 21 [(validate.rules).enum = {defined_only: true}];

  // Maximum bytes of early data to buffer from the downstream connection before
  // the upstream connection is established.
  //
  // If not set, the TCP proxy will read-disable the downstream connection until the
  // upstream connection is established (legacy behavior).
  //
  // If set, enables ``receive_before_connect`` mode where the filter allows the filter
  // chain to read downstream data before the upstream connection exists. The data is
  // buffered and forwarded once the upstream connection is ready. When the buffer exceeds
  // this limit, the downstream connection is read-disabled to prevent excessive memory usage.
  //
  // This field is required when ``upstream_connect_mode`` is ``ON_DOWNSTREAM_DATA``.
  //
  // .. note::
  //   Use this carefully with server-first protocols. The upstream may send data before
  //   receiving anything from downstream, which could fill the early data buffer.

Review comment (suggestion):
I think we need to be careful with how we handle merge vs override, when considering https://github.com/envoyproxy/envoy/issues/42075. Would it ever make sense to add an additional TLV of the same key? Maybe we should use an enum instead of a bool here so that if different behaviors are needed in the future we can easily add it to the API.

Code after:

  // Additional access log options for the TCP proxy.
  TcpAccessLogOptions access_log_options = 17;

  // TLVs to add to the PROXY protocol header sent upstream. Behavior when PROXY protocol
  // state already exists (e.g., downstream TLVs from proxy_protocol listener filter) is
  // controlled by ``proxy_protocol_tlv_merge_policy``.
  //
  // .. note::
  //   To ensure the TLVs are allowed upstream, configure passthrough TLVs on the upstream
  //   proxy protocol transport. See :ref:`core.v3.ProxyProtocolConfig.pass_through_tlvs
  //   <envoy_v3_api_field_config.core.v3.ProxyProtocolConfig.pass_through_tlvs>` for details.
  repeated config.core.v3.TlvEntry proxy_protocol_tlvs = 19;

  // Specifies how TLVs in ``proxy_protocol_tlvs`` are merged with existing PROXY protocol state
  // (e.g., downstream TLVs from the proxy_protocol listener filter). See
  // :ref:`ProxyProtocolTlvMergePolicy
  // <envoy_v3_api_enum_extensions.filters.network.tcp_proxy.v3.ProxyProtocolTlvMergePolicy>`.
  ProxyProtocolTlvMergePolicy proxy_protocol_tlv_merge_policy = 23
      [(validate.rules).enum = {defined_only: true}];

  // Specifies when to establish the upstream connection.
  //
  // When not specified, defaults to ``IMMEDIATE`` for backward compatibility.
  //
  // .. attention::
  //   Server-first protocols (e.g., SMTP, MySQL, POP3) require ``IMMEDIATE`` mode.
  UpstreamConnectMode upstream_connect_mode = 21 [(validate.rules).enum = {defined_only: true}];

  // Maximum bytes of early data to buffer from the downstream connection before
  // the upstream connection is established.
  //
  // If not set, the TCP proxy will read-disable the downstream connection until the
  // upstream connection is established (legacy behavior).
  //
  // If set, enables ``receive_before_connect`` mode where the filter allows the filter
  // chain to read downstream data before the upstream connection exists. The data is
  // buffered and forwarded once the upstream connection is ready. When the buffer exceeds
  // this limit, the downstream connection is read-disabled to prevent excessive memory usage.
  //
  // This field is required when ``upstream_connect_mode`` is not ``IMMEDIATE``.
  //
  // .. note::
  //   Use this carefully with server-first protocols. The upstream may send data before
  //   receiving anything from downstream, which could fill the early data buffer.
  google.protobuf.UInt32Value max_early_data_bytes = 22 [(validate.rules).uint32 = {lte: 1048576}];
}