tcp_proxy: added changes to support ppv2 tlvs to be merged when downstream proxy protocol values are present#42824
Conversation
…tocol values are present Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
|
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
| // When set to true and the connection already contains ``PROXY`` protocol state | ||
| // (including TLVs) from a downstream proxy protocol listener filter, the TLVs | ||
| // specified in ``proxy_protocol_tlvs`` are merged with the downstream TLVs. | ||
| // | ||
| // **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). | ||
| // | ||
| // When set to false (default), the ``proxy_protocol_tlvs`` are ignored if | ||
| // downstream ``PROXY`` protocol state already exists. | ||
| bool merge_proxy_protocol_tlvs = 23; |
There was a problem hiding this comment.
I would suggest calling it merge_with_downstream_tlvs to be more clear and also add more info to the docs.
| // When set to true and the connection already contains ``PROXY`` protocol state | |
| // (including TLVs) from a downstream proxy protocol listener filter, the TLVs | |
| // specified in ``proxy_protocol_tlvs`` are merged with the downstream TLVs. | |
| // | |
| // **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). | |
| // | |
| // When set to false (default), the ``proxy_protocol_tlvs`` are ignored if | |
| // downstream ``PROXY`` protocol state already exists. | |
| bool merge_proxy_protocol_tlvs = 23; | |
| // Controls whether TLVs specified in ``proxy_protocol_tlvs`` are merged with downstream | |
| // ``PROXY`` protocol TLVs when downstream ``PROXY`` protocol state already exists. | |
| // | |
| // When set to ``true`` and the connection already contains ``PROXY`` protocol state | |
| // (including TLVs) from a downstream proxy protocol listener filter, the TLVs | |
| // specified in ``proxy_protocol_tlvs`` are merged with the downstream TLVs. | |
| // | |
| // 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; |
There was a problem hiding this comment.
Makes sense. I've made the changes to rename the field along with the doc suggestions
|
/assign @ggreenway |
…ith_downstream_tlvs Signed-off-by: Prasad I V <prasad.iv@databricks.com>
| // 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; |
There was a problem hiding this comment.
I think we need to be careful with how we handle merge vs override, when considering #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.
There was a problem hiding this comment.
Makes sense to add the enum config option. I've now updated the code to use enum downstream_tlv_merge_policy with 3 different options(KEEP_DOWNSTREAM_ONLY, OVERRIDE_DOWNSTREAM_TLVS_BY_TYPE, APPEND_TO_DOWNSTREAM_TLVS)
|
|
||
| // Add downstream TLVs that don't conflict with tcp_proxy TLVs. | ||
| for (const auto& tlv : existing_data.tlv_vector_) { | ||
| if (!seen_types.contains(tlv.type)) { |
There was a problem hiding this comment.
This will introduce the bug reported in #42075 to tcp_proxy.
There was a problem hiding this comment.
Fixed this now with explicit enum values
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
|
@ggreenway I've addressed the review comments. Can you please have a look |
|
Gentle ping @ggreenway from maintainer oncall. Please merge main to resolve the conflict as well @ivpr Thanks! |
|
Apologies; I've been very busy and haven't had time to review this yet. I'm hoping to get to it early next week. |
Signed-off-by: ivpr <ivijayprasad@gmail.com>
ggreenway
left a comment
There was a problem hiding this comment.
Apologies for the delayed review.
This looks good at a high level, but there's a little bit of clarifying/simplifying the docs and semantics to do.
/wait
| // 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. |
There was a problem hiding this comment.
But if there is no downstream PROXY protocol, then the configured TLVs are used instead. Please document/clarify this behavior.
| // - ``KEEP_DOWNSTREAM_ONLY`` (default): The TLVs specified in ``proxy_protocol_tlvs`` are | ||
| // ignored if downstream ``PROXY`` protocol state already exists. Only the downstream TLVs | ||
| // are forwarded to the upstream. | ||
| // | ||
| // - ``OVERRIDE_DOWNSTREAM_TLVS_BY_TYPE``: TLVs specified in ``proxy_protocol_tlvs`` override | ||
| // downstream TLVs with the same type. TLVs with non-conflicting types from both sources are | ||
| // preserved. The source/destination addresses from the downstream ``PROXY`` protocol state | ||
| // are preserved (not modified). | ||
| // | ||
| // - ``APPEND_TO_DOWNSTREAM_TLVS``: The TLVs specified in ``proxy_protocol_tlvs`` are appended | ||
| // to the downstream TLVs. This preserves all downstream TLVs and adds the tcp_proxy TLVs. | ||
| // The PROXY protocol v2 specification allows multiple TLVs with the same type, so this mode | ||
| // preserves all TLVs from both sources. |
There was a problem hiding this comment.
These docs should all be in the enum definition above; no need to duplicate here
| // .. 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. |
There was a problem hiding this comment.
This is confusing behavior.
I think it would be clearer if the default option was something like ADD_IF_ABSENT (taken from https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/base.proto#envoy-v3-api-enum-config-core-v3-headervalueoption-headerappendaction), and the other two options then can be said to be in effect, regardless of whether there's downstream TLVs or not (because if there aren't, both of those options just add all the configured TLVs).
I think the net effect is the same, but the mental model for how it works is simpler. WDYT?
| parseTLVs(config.proxy_protocol_tlvs(), context, dynamic_tlv_formatters_); | ||
| } | ||
|
|
||
| downstream_tlv_merge_policy_ = config.downstream_tlv_merge_policy(); |
There was a problem hiding this comment.
This should be set in the initializer list at the top of the constructor, because it has no validation or complicated conversion logic.
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: ivpr <ivijayprasad@gmail.com>
| * ``ADD_IF_ABSENT`` (default): Add configured TLVs only if no state exists. | ||
| * ``OVERWRITE_BY_TYPE_IF_EXISTS_OR_ADD``: Overwrite existing TLVs by type with configured TLVs. | ||
| Non-conflicting TLVs from both sources are preserved. | ||
| * ``APPEND_IF_EXISTS_OR_ADD``: Append configured TLVs to existing TLVs, preserving all | ||
| TLVs from both sources (allows duplicate types per PROXY protocol v2 spec). | ||
|
|
There was a problem hiding this comment.
I don't think you need to repeat this from the proto docs; just link to the enum type
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: ivpr <ivijayprasad@gmail.com>
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
|
/retest |
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Signed-off-by: ivpr <ivijayprasad@gmail.com>
|
/retest |
ggreenway
left a comment
There was a problem hiding this comment.
LGTM. @markdroth can you review API please?
|
/lgtm api |
…tream proxy protocol values are present (envoyproxy#42824) Signed-off-by: nick <nickshokri@google.com>
…tream proxy protocol values are present (envoyproxy#42824) Signed-off-by: nick <nickshokri@google.com>
…tream proxy protocol values are present (envoyproxy#42824)
| Network::ProxyProtocolFilterState::key())) { | ||
| // Evaluate dynamic TLVs with the connection's stream info. | ||
|
|
||
| auto* existing_state = filter_state->getDataMutable<Network::ProxyProtocolFilterState>( |
There was a problem hiding this comment.
This assumes that the ProxyProtocolFilterState was added as a mutable element. What behavior do you expect if it was added as an immutable element?
…tream proxy protocol values are present (envoyproxy#42824)
Currently proxy_protocol_tlvs field in tcp_proxy ignores the TLVs specified when downstream has proxy protocol data. This change adds support to be able to merge the TLVs through an explicit enum field
proxy_protocol_tlv_merge_policy.Added support for 3 options
ADD_IF_ABSENT(default): 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.OVERWRITE_BY_TYPE_IF_EXISTS_OR_ADD: 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..APPEND_IF_EXISTS_OR_ADD: 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.Commit Message: tcp_proxy: added changes to support ppv2 tlvs to be merged when downstream proxy protocol values are present
Additional Description: Currently proxy_protocol_tlvs field in tcp_proxy ignores the TLVs specified when downstream has proxy protocol data. This changes adds support to merge the TLVs through an explicit field
proxy_protocol_tlv_merge_policy.Risk Level: Low
Testing: Unit tests
Docs Changes: Added
Release Notes: Added
Platform Specific Features: N/A
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]