From cd28fa4ec7d1e14c38844b44c665344581c89ce2 Mon Sep 17 00:00:00 2001 From: "data-plane-api(Azure Pipelines)" Date: Mon, 15 Mar 2021 22:07:47 +0000 Subject: [PATCH] udp: allow configurable max packet size (#15388) 1) Add configuration for max packet size to UDP listeners 2) Add configuration for max packet size to UDP proxy filter 3) Fix crashing issue when a GRO receive is truncated. This was fixed in the open because GRO recieve does not support IP fragmentation, thus the previous size of 24000 bytes was large enough to receive a jumbo frame size datagram. The issue is now exposed by allowing packet size to be configured larger. 4) Reorganize code and some config around UDP listeners to streamline the logic when the listener is a UDP listener. Also moved the UDP batch writer configuration to a better place since it's still effectively alpha and was marked not implemented. Fixes https://github.com/envoyproxy/envoy/issues/15327 Signed-off-by: Matt Klein Mirrored from https://github.com/envoyproxy/envoy @ 73eec645a39343eec33b5d61bf492ba49c397cfe --- envoy/config/listener/v3/listener.proto | 19 ++------- .../listener/v3/listener_components.proto | 2 +- envoy/config/listener/v3/quic_config.proto | 8 ++-- .../v3/udp_gso_batch_writer_config.proto | 6 ++- .../listener/v3/udp_listener_config.proto | 41 +++++++++++++------ envoy/config/listener/v4alpha/listener.proto | 19 ++------- .../v4alpha/listener_components.proto | 2 +- .../config/listener/v4alpha/quic_config.proto | 8 ++-- .../v4alpha/udp_gso_batch_writer_config.proto | 6 ++- .../v4alpha/udp_listener_config.proto | 41 +++++++++++++------ .../filters/udp/udp_proxy/v3/udp_proxy.proto | 9 +++- .../quic/v3/quic_transport.proto | 3 +- .../quic/v4alpha/quic_transport.proto | 3 +- 13 files changed, 92 insertions(+), 75 deletions(-) diff --git a/envoy/config/listener/v3/listener.proto b/envoy/config/listener/v3/listener.proto index 7d0085aa..390bc898 100644 --- a/envoy/config/listener/v3/listener.proto +++ b/envoy/config/listener/v3/listener.proto @@ -5,7 +5,6 @@ package envoy.config.listener.v3; import "envoy/config/accesslog/v3/accesslog.proto"; import "envoy/config/core/v3/address.proto"; import "envoy/config/core/v3/base.proto"; -import "envoy/config/core/v3/extension.proto"; import "envoy/config/core/v3/socket_option.proto"; import "envoy/config/listener/v3/api_listener.proto"; import "envoy/config/listener/v3/listener_components.proto"; @@ -93,7 +92,7 @@ message Listener { message InternalListenerConfig { } - reserved 14; + reserved 14, 23; // The unique name by which this listener is known. If no name is provided, // Envoy will allocate an internal UUID for the listener. If the listener is to be dynamically @@ -216,10 +215,8 @@ message Listener { // If the protocol in the listener socket address in :ref:`protocol // ` is :ref:`UDP - // `, this field specifies the actual udp - // listener to create, i.e. :ref:`udp_listener_name - // ` = "raw_udp_listener" for - // creating a packet-oriented UDP listener. If not present, treat it as "raw_udp_listener". + // `, this field specifies UDP + // listener specific configuration. UdpListenerConfig udp_listener_config = 18; // Used to represent an API listener, which is used in non-proxy clients. The type of API @@ -261,16 +258,6 @@ message Listener { // emitted by this listener. repeated accesslog.v3.AccessLog access_log = 22; - // If the protocol in the listener socket address in :ref:`protocol - // ` is :ref:`UDP - // `, this field specifies the actual udp - // writer to create, i.e. :ref:`name ` - // = "udp_default_writer" for creating a udp writer with writing in passthrough mode, - // = "udp_gso_batch_writer" for creating a udp writer with writing in batch mode. - // If not present, treat it as "udp_default_writer". - // [#not-implemented-hide:] - core.v3.TypedExtensionConfig udp_writer_config = 23; - // The maximum length a tcp listener's pending connections queue can grow to. If no value is // provided net.core.somaxconn will be used on Linux and 128 otherwise. google.protobuf.UInt32Value tcp_backlog_size = 24; diff --git a/envoy/config/listener/v3/listener_components.proto b/envoy/config/listener/v3/listener_components.proto index c9a0e15d..dc9332cf 100644 --- a/envoy/config/listener/v3/listener_components.proto +++ b/envoy/config/listener/v3/listener_components.proto @@ -338,7 +338,7 @@ message ListenerFilter { oneof config_type { // Filter specific configuration which depends on the filter being // instantiated. See the supported filters for further documentation. - // [#extension-category: envoy.filters.listener] + // [#extension-category: envoy.filters.listener,envoy.filters.udp_listener] google.protobuf.Any typed_config = 3; } diff --git a/envoy/config/listener/v3/quic_config.proto b/envoy/config/listener/v3/quic_config.proto index 39f46f0f..658389ed 100644 --- a/envoy/config/listener/v3/quic_config.proto +++ b/envoy/config/listener/v3/quic_config.proto @@ -15,11 +15,11 @@ option java_outer_classname = "QuicConfigProto"; option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = ACTIVE; -// [#protodoc-title: QUIC listener Config] -// [#extension: envoy.listener.quic] +// [#protodoc-title: QUIC listener config] +// [#comment:#extension: envoy.udp_listeners.quiche_quic_listener] +// [#comment:TODO(#12829): Remove this as an extension point.] -// Configuration specific to the QUIC protocol. -// Next id: 5 +// Configuration specific to the UDP QUIC listener. message QuicProtocolOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.listener.QuicProtocolOptions"; diff --git a/envoy/config/listener/v3/udp_gso_batch_writer_config.proto b/envoy/config/listener/v3/udp_gso_batch_writer_config.proto index fc9c48af..75904d68 100644 --- a/envoy/config/listener/v3/udp_gso_batch_writer_config.proto +++ b/envoy/config/listener/v3/udp_gso_batch_writer_config.proto @@ -9,9 +9,11 @@ option java_outer_classname = "UdpGsoBatchWriterConfigProto"; option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = ACTIVE; -// [#protodoc-title: Udp Gso Batch Writer Config] +// [#protodoc-title: UDP GSO Batch Writer] +// [#comment:#extension: envoy.udp_packet_writers.udp_gso_batch_writer] +// Configuration specific to the UDP GSO Batch Writer. // [#not-implemented-hide:] -// Configuration specific to the Udp Gso Batch Writer. +// [#comment:TODO(#12829): Remove this as an extension point.] message UdpGsoBatchWriterOptions { } diff --git a/envoy/config/listener/v3/udp_listener_config.proto b/envoy/config/listener/v3/udp_listener_config.proto index 058bca55..2898bf4b 100644 --- a/envoy/config/listener/v3/udp_listener_config.proto +++ b/envoy/config/listener/v3/udp_listener_config.proto @@ -2,38 +2,53 @@ syntax = "proto3"; package envoy.config.listener.v3; +import "envoy/config/core/v3/extension.proto"; + import "google/protobuf/any.proto"; +import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; option java_package = "io.envoyproxy.envoy.config.listener.v3"; option java_outer_classname = "UdpListenerConfigProto"; option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = ACTIVE; -// [#protodoc-title: UDP Listener Config] +// [#protodoc-title: UDP listener config] // Listener :ref:`configuration overview ` +// [#next-free-field: 7] message UdpListenerConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.listener.UdpListenerConfig"; - reserved 2; + reserved 1, 2, 3; reserved "config"; - // Used to look up UDP listener factory, matches "raw_udp_listener" or - // "quic_listener" to create a specific udp listener. - // If not specified, treat as "raw_udp_listener". - string udp_listener_name = 1; - - // Used to create a specific listener factory. To some factory, e.g. - // "raw_udp_listener", config is not needed. - // [#extension-category: envoy.filters.udp_listener] - oneof config_type { - google.protobuf.Any typed_config = 3; - } + // Used to create a specific UDP listener factory. If not specified the default UDP listener is + // used. + // [#comment:#extension-category: envoy.udp_listeners] + // [#not-implemented-hide:] + // [#comment:TODO(#12829): Remove this as an extension point.] + core.v3.TypedExtensionConfig listener_config = 4; + + // The maximum size of received downstream UDP datagrams. Using a larger size will cause Envoy to allocate + // more memory per listener. Received datagrams above this size will be dropped. If not set + // defaults to 1500 bytes. + google.protobuf.UInt64Value max_downstream_rx_datagram_size = 5 + [(validate.rules).uint64 = {lt: 65536 gt: 0}]; + + // If the protocol in the listener socket address in :ref:`protocol + // ` is :ref:`UDP + // `, this field specifies the + // actual UDP writer to create. If not specified the default UDP writer is used. + // [#comment:#extension-category: envoy.udp_packet_writers] + // [#not-implemented-hide:] + // [#comment:TODO(#12829): Remove this as an extension point.] + core.v3.TypedExtensionConfig writer_config = 6; } message ActiveRawUdpListenerConfig { diff --git a/envoy/config/listener/v4alpha/listener.proto b/envoy/config/listener/v4alpha/listener.proto index dd58aa2d..b514fcd2 100644 --- a/envoy/config/listener/v4alpha/listener.proto +++ b/envoy/config/listener/v4alpha/listener.proto @@ -5,7 +5,6 @@ package envoy.config.listener.v4alpha; import "envoy/config/accesslog/v4alpha/accesslog.proto"; import "envoy/config/core/v4alpha/address.proto"; import "envoy/config/core/v4alpha/base.proto"; -import "envoy/config/core/v4alpha/extension.proto"; import "envoy/config/core/v4alpha/socket_option.proto"; import "envoy/config/listener/v4alpha/api_listener.proto"; import "envoy/config/listener/v4alpha/listener_components.proto"; @@ -98,7 +97,7 @@ message Listener { "envoy.config.listener.v3.Listener.InternalListenerConfig"; } - reserved 14, 7; + reserved 14, 23, 7; reserved "deprecated_v1"; @@ -220,10 +219,8 @@ message Listener { // If the protocol in the listener socket address in :ref:`protocol // ` is :ref:`UDP - // `, this field specifies the actual udp - // listener to create, i.e. :ref:`udp_listener_name - // ` = "raw_udp_listener" for - // creating a packet-oriented UDP listener. If not present, treat it as "raw_udp_listener". + // `, this field specifies UDP + // listener specific configuration. UdpListenerConfig udp_listener_config = 18; // Used to represent an API listener, which is used in non-proxy clients. The type of API @@ -265,16 +262,6 @@ message Listener { // emitted by this listener. repeated accesslog.v4alpha.AccessLog access_log = 22; - // If the protocol in the listener socket address in :ref:`protocol - // ` is :ref:`UDP - // `, this field specifies the actual udp - // writer to create, i.e. :ref:`name ` - // = "udp_default_writer" for creating a udp writer with writing in passthrough mode, - // = "udp_gso_batch_writer" for creating a udp writer with writing in batch mode. - // If not present, treat it as "udp_default_writer". - // [#not-implemented-hide:] - core.v4alpha.TypedExtensionConfig udp_writer_config = 23; - // The maximum length a tcp listener's pending connections queue can grow to. If no value is // provided net.core.somaxconn will be used on Linux and 128 otherwise. google.protobuf.UInt32Value tcp_backlog_size = 24; diff --git a/envoy/config/listener/v4alpha/listener_components.proto b/envoy/config/listener/v4alpha/listener_components.proto index 9931ea7a..418129dc 100644 --- a/envoy/config/listener/v4alpha/listener_components.proto +++ b/envoy/config/listener/v4alpha/listener_components.proto @@ -330,7 +330,7 @@ message ListenerFilter { oneof config_type { // Filter specific configuration which depends on the filter being // instantiated. See the supported filters for further documentation. - // [#extension-category: envoy.filters.listener] + // [#extension-category: envoy.filters.listener,envoy.filters.udp_listener] google.protobuf.Any typed_config = 3; } diff --git a/envoy/config/listener/v4alpha/quic_config.proto b/envoy/config/listener/v4alpha/quic_config.proto index 59e76ae3..f9c6d02b 100644 --- a/envoy/config/listener/v4alpha/quic_config.proto +++ b/envoy/config/listener/v4alpha/quic_config.proto @@ -15,11 +15,11 @@ option java_outer_classname = "QuicConfigProto"; option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSION_CANDIDATE; -// [#protodoc-title: QUIC listener Config] -// [#extension: envoy.listener.quic] +// [#protodoc-title: QUIC listener config] +// [#comment:#extension: envoy.udp_listeners.quiche_quic_listener] +// [#comment:TODO(#12829): Remove this as an extension point.] -// Configuration specific to the QUIC protocol. -// Next id: 5 +// Configuration specific to the UDP QUIC listener. message QuicProtocolOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.config.listener.v3.QuicProtocolOptions"; diff --git a/envoy/config/listener/v4alpha/udp_gso_batch_writer_config.proto b/envoy/config/listener/v4alpha/udp_gso_batch_writer_config.proto index 0a8ed00e..87625555 100644 --- a/envoy/config/listener/v4alpha/udp_gso_batch_writer_config.proto +++ b/envoy/config/listener/v4alpha/udp_gso_batch_writer_config.proto @@ -10,10 +10,12 @@ option java_outer_classname = "UdpGsoBatchWriterConfigProto"; option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSION_CANDIDATE; -// [#protodoc-title: Udp Gso Batch Writer Config] +// [#protodoc-title: UDP GSO Batch Writer] +// [#comment:#extension: envoy.udp_packet_writers.udp_gso_batch_writer] +// Configuration specific to the UDP GSO Batch Writer. // [#not-implemented-hide:] -// Configuration specific to the Udp Gso Batch Writer. +// [#comment:TODO(#12829): Remove this as an extension point.] message UdpGsoBatchWriterOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.config.listener.v3.UdpGsoBatchWriterOptions"; diff --git a/envoy/config/listener/v4alpha/udp_listener_config.proto b/envoy/config/listener/v4alpha/udp_listener_config.proto index 9d6a3917..0b4bca47 100644 --- a/envoy/config/listener/v4alpha/udp_listener_config.proto +++ b/envoy/config/listener/v4alpha/udp_listener_config.proto @@ -2,38 +2,53 @@ syntax = "proto3"; package envoy.config.listener.v4alpha; +import "envoy/config/core/v4alpha/extension.proto"; + import "google/protobuf/any.proto"; +import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; option java_package = "io.envoyproxy.envoy.config.listener.v4alpha"; option java_outer_classname = "UdpListenerConfigProto"; option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSION_CANDIDATE; -// [#protodoc-title: UDP Listener Config] +// [#protodoc-title: UDP listener config] // Listener :ref:`configuration overview ` +// [#next-free-field: 7] message UdpListenerConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.config.listener.v3.UdpListenerConfig"; - reserved 2; + reserved 1, 2, 3; reserved "config"; - // Used to look up UDP listener factory, matches "raw_udp_listener" or - // "quic_listener" to create a specific udp listener. - // If not specified, treat as "raw_udp_listener". - string udp_listener_name = 1; - - // Used to create a specific listener factory. To some factory, e.g. - // "raw_udp_listener", config is not needed. - // [#extension-category: envoy.filters.udp_listener] - oneof config_type { - google.protobuf.Any typed_config = 3; - } + // Used to create a specific UDP listener factory. If not specified the default UDP listener is + // used. + // [#comment:#extension-category: envoy.udp_listeners] + // [#not-implemented-hide:] + // [#comment:TODO(#12829): Remove this as an extension point.] + core.v4alpha.TypedExtensionConfig listener_config = 4; + + // The maximum size of received downstream UDP datagrams. Using a larger size will cause Envoy to allocate + // more memory per listener. Received datagrams above this size will be dropped. If not set + // defaults to 1500 bytes. + google.protobuf.UInt64Value max_downstream_rx_datagram_size = 5 + [(validate.rules).uint64 = {lt: 65536 gt: 0}]; + + // If the protocol in the listener socket address in :ref:`protocol + // ` is :ref:`UDP + // `, this field specifies the + // actual UDP writer to create. If not specified the default UDP writer is used. + // [#comment:#extension-category: envoy.udp_packet_writers] + // [#not-implemented-hide:] + // [#comment:TODO(#12829): Remove this as an extension point.] + core.v4alpha.TypedExtensionConfig writer_config = 6; } message ActiveRawUdpListenerConfig { diff --git a/envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.proto b/envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.proto index 1e986434..3cc70264 100644 --- a/envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.proto +++ b/envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package envoy.extensions.filters.udp.udp_proxy.v3; import "google/protobuf/duration.proto"; +import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; @@ -18,7 +19,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#extension: envoy.filters.udp_listener.udp_proxy] // Configuration for the UDP proxy filter. -// [#next-free-field: 6] +// [#next-free-field: 7] message UdpProxyConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.udp.udp_proxy.v2alpha.UdpProxyConfig"; @@ -68,4 +69,10 @@ message UdpProxyConfig { // load balancing algorithms will select a host randomly. Currently the number of hash policies is // limited to 1. repeated HashPolicy hash_policies = 5 [(validate.rules).repeated = {max_items: 1}]; + + // The maximum size of received upstream UDP datagrams. Using a larger size will cause Envoy to allocate + // more memory per listener. Received datagrams above this size will be dropped. If not set + // defaults to 1500 bytes. + google.protobuf.UInt64Value max_upstream_rx_datagram_size = 6 + [(validate.rules).uint64 = {lt: 65536 gt: 0}]; } diff --git a/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto b/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto index 62c954f7..7f713c0f 100644 --- a/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto +++ b/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto @@ -13,7 +13,8 @@ option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: quic transport] -// [#extension: envoy.transport_sockets.quic] +// [#comment:#extension: envoy.transport_sockets.quic] +// [#comment:TODO(#12829): Remove this as an extension point.] // Configuration for Downstream QUIC transport socket. This provides Google's implementation of Google QUIC and IETF QUIC to Envoy. message QuicDownstreamTransport { diff --git a/envoy/extensions/transport_sockets/quic/v4alpha/quic_transport.proto b/envoy/extensions/transport_sockets/quic/v4alpha/quic_transport.proto index 255bfe62..5f5f7d39 100644 --- a/envoy/extensions/transport_sockets/quic/v4alpha/quic_transport.proto +++ b/envoy/extensions/transport_sockets/quic/v4alpha/quic_transport.proto @@ -14,7 +14,8 @@ option java_multiple_files = true; option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSION_CANDIDATE; // [#protodoc-title: quic transport] -// [#extension: envoy.transport_sockets.quic] +// [#comment:#extension: envoy.transport_sockets.quic] +// [#comment:TODO(#12829): Remove this as an extension point.] // Configuration for Downstream QUIC transport socket. This provides Google's implementation of Google QUIC and IETF QUIC to Envoy. message QuicDownstreamTransport {