Skip to content

Commit

Permalink
quic: upstream sends early data requests (envoyproxy#20167)
Browse files Browse the repository at this point in the history
Commit Message: make HTTP/3 upstream sends 0-RTT (early data) requests if it has cached 0-RTT credentials. Add a config knob in RouteAction to specify which request can be sent over early data, which by default are HTTP safe methods.

Risk Level: high, changes to conn pool behavior though should only take effect for h3 pool
Testing: added h3 upstream integration tests.
Docs Changes: N/A
Release Notes: changes to docs/root/version_history/current.rst
Platform Specific Features: N/A
Runtime guard: envoy.reloadable_features.http3_sends_early_data
Fixes envoyproxy#18715, envoyproxy#19542
Signed-off-by: Dan Zhang <[email protected]>


Signed-off-by: Dan Zhang <[email protected]>
  • Loading branch information
danzh2010 authored May 23, 2022
1 parent a9b756d commit 8ce13d7
Show file tree
Hide file tree
Showing 43 changed files with 1,085 additions and 84 deletions.
1 change: 1 addition & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ proto_library(
"//envoy/extensions/compression/zstd/compressor/v3:pkg",
"//envoy/extensions/compression/zstd/decompressor/v3:pkg",
"//envoy/extensions/config/validators/minimum_clusters/v3:pkg",
"//envoy/extensions/early_data/v3:pkg",
"//envoy/extensions/filters/common/dependency/v3:pkg",
"//envoy/extensions/filters/common/fault/v3:pkg",
"//envoy/extensions/filters/common/matcher/action/v3:pkg",
Expand Down
7 changes: 6 additions & 1 deletion api/envoy/config/route/v3/route_components.proto
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ message CorsPolicy {
core.v3.RuntimeFractionalPercent shadow_enabled = 10;
}

// [#next-free-field: 40]
// [#next-free-field: 41]
message RouteAction {
option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RouteAction";

Expand Down Expand Up @@ -1147,6 +1147,11 @@ message RouteAction {
// :ref:`HTTP_DOWNSTREAM_STREAM_IDLE <envoy_v3_api_enum_value_config.overload.v3.ScaleTimersOverloadActionConfig.TimerType.HTTP_DOWNSTREAM_STREAM_IDLE>`.
google.protobuf.Duration idle_timeout = 24;

// Specifies how to send request over TLS early data.
// If absent, allows `safe HTTP requests <https://www.rfc-editor.org/rfc/rfc7231#section-4.2.1>`_ to be sent on early data.
// [#extension-category: envoy.route.early_data_policy]
core.v3.TypedExtensionConfig early_data_policy = 40;

// Indicates that the route has a retry policy. Note that if this is set,
// it'll take precedence over the virtual host level retry policy entirely
// (e.g.: policies are not merged, most internal one becomes the enforced policy).
Expand Down
9 changes: 9 additions & 0 deletions api/envoy/extensions/early_data/v3/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"],
)
18 changes: 18 additions & 0 deletions api/envoy/extensions/early_data/v3/default_early_data_policy.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";

package envoy.extensions.early_data.v3;

import "udpa/annotations/status.proto";

option java_package = "io.envoyproxy.envoy.extensions.early_data.v3";
option java_outer_classname = "DefaultEarlyDataPolicyProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/early_data/v3;early_datav3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: HTTP request early data policy]

// [#extension: envoy.route.early_data_policy.default]
// The default rule to allow/disallow a request to be sent as early data. It's an empty config now. Configuring it will disallow any request to be sent over early data.
message DefaultEarlyDataPolicy {
}
1 change: 1 addition & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ proto_library(
"//envoy/extensions/compression/zstd/compressor/v3:pkg",
"//envoy/extensions/compression/zstd/decompressor/v3:pkg",
"//envoy/extensions/config/validators/minimum_clusters/v3:pkg",
"//envoy/extensions/early_data/v3:pkg",
"//envoy/extensions/filters/common/dependency/v3:pkg",
"//envoy/extensions/filters/common/fault/v3:pkg",
"//envoy/extensions/filters/common/matcher/action/v3:pkg",
Expand Down
3 changes: 3 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ new_features:
- area: http
change: |
preserve case header formatter support innner formatter on Envoy headers in :ref:`formatter_type_on_envoy_headers <envoy_v3_api_field_extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig.formatter_type_on_envoy_headers>`.
- area: http3
change: |
added :ref:`early_data_policy <envoy_v3_api_field_config.route.v3.RouteAction.early_data_policy>` extension to allow upstream HTTP/3 sending requests over early data. If no extension is configured, HTTP/3 pool will send safe requests as early data to the host if the pool already cached 0-RTT credentials of that host. If those requests fail and the underlying connection pool supports TCP fallback, the request may be retried automatically. If the :ref:`default extension <envoy_v3_api_msg_extensions.early_data.v3.DefaultEarlyDataPolicy>` is configured, no requests are allowed to be sent as early data. Note that if any customized extension configures non-safe requests to be allowed over early data, the Envoy will not automatically retry them. If desired, explicitly config their :ref:`retry_policy <envoy_v3_api_field_config.route.v3.RouteAction.retry_policy>`. This feature requires both ``envoy.reloadable_features.conn_pool_new_stream_with_early_data_and_http3`` and ``envoy.reloadable_features.http3_sends_early_data`` to be turned on.
- area: thrift
change: |
added flag to router to control downstream local close. :ref:`close_downstream_on_upstream_error <envoy_v3_api_field_extensions.filters.network.thrift_proxy.router.v3.Router.close_downstream_on_upstream_error>`.
Expand Down
1 change: 1 addition & 0 deletions docs/root/api-v3/common_messages/common_messages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Common messages
../config/common/key_value/v3/config.proto
../config/common/mutation_rules/v3/mutation_rules.proto
../extensions/common/ratelimit/v3/ratelimit.proto
../extensions/early_data/v3/default_early_data_policy.proto
../extensions/filters/common/fault/v3/fault.proto
../extensions/network/socket_interface/v3/default_socket_interface.proto
../extensions/common/matching/v3/extension_matcher.proto
Expand Down
37 changes: 37 additions & 0 deletions envoy/router/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,38 @@ class PathMatchCriterion {
*/
class HttpRouteTypedMetadataFactory : public Envoy::Config::TypedMetadataFactory {};

/**
* Base class for all early data option extensions.
*/
class EarlyDataPolicy {
public:
virtual ~EarlyDataPolicy() = default;

/**
* @return bool whether the given request may be sent over early data.
*/
virtual bool allowsEarlyDataForRequest(const Http::RequestHeaderMap& request_headers) const PURE;
};

using EarlyDataPolicyPtr = std::unique_ptr<EarlyDataPolicy>;

/**
* Base class for all early data option factories.
*/
class EarlyDataPolicyFactory : public Envoy::Config::TypedFactory {
public:
~EarlyDataPolicyFactory() override = default;

/**
* @param config the typed config for early data option.
* @return EarlyDataIOptionPtr an instance of EarlyDataPolicy.
*/
virtual EarlyDataPolicyPtr createEarlyDataPolicy(const Protobuf::Message& config) PURE;

// Config::UntypedFactory
std::string category() const override { return "envoy.route.early_data_policy"; }
};

/**
* An individual resolved route entry.
*/
Expand Down Expand Up @@ -996,6 +1028,11 @@ class RouteEntry : public ResponseEntry {
* @return std::string& the name of the route.
*/
virtual const std::string& routeName() const PURE;

/**
* @return EarlyDataPolicy& the configured early data option.
*/
virtual const EarlyDataPolicy& earlyDataPolicy() const PURE;
};

/**
Expand Down
2 changes: 2 additions & 0 deletions envoy/upstream/upstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ class PrioritySet {
COUNTER(upstream_rq_pending_failure_eject) \
COUNTER(upstream_rq_pending_overflow) \
COUNTER(upstream_rq_pending_total) \
COUNTER(upstream_rq_0rtt) \
COUNTER(upstream_rq_per_try_timeout) \
COUNTER(upstream_rq_per_try_idle_timeout) \
COUNTER(upstream_rq_retry) \
Expand All @@ -588,6 +589,7 @@ class PrioritySet {
COUNTER(upstream_rq_timeout) \
COUNTER(upstream_rq_total) \
COUNTER(upstream_rq_tx_reset) \
COUNTER(upstream_http3_broken) \
GAUGE(lb_subsets_active, Accumulate) \
GAUGE(max_host_weight, NeverImport) \
GAUGE(membership_degraded, NeverImport) \
Expand Down
Loading

0 comments on commit 8ce13d7

Please sign in to comment.