From f239572084eb4275933ec415c69898086e0656f3 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 4 Aug 2023 17:08:01 +0300 Subject: [PATCH 1/2] Added config for socket options for listeners New config field was added to support DSCP marking for outbound traffic, for both IPv4 (TOS field) and IPv6 (Traffic Class field). Signed-off-by: Tero Saarni --- apis/projectcontour/v1alpha1/contourconfig.go | 24 +++ .../v1alpha1/zz_generated.deepcopy.go | 20 ++ changelogs/unreleased/5352-tsaarni-small.md | 1 + cmd/contour/serve.go | 1 + cmd/contour/servecontext.go | 4 + cmd/contour/servecontext_test.go | 4 + examples/contour/01-contour-config.yaml | 6 + examples/contour/01-crds.yaml | 53 +++++ examples/render/contour-deployment.yaml | 59 +++++ .../render/contour-gateway-provisioner.yaml | 53 +++++ examples/render/contour-gateway.yaml | 59 +++++ examples/render/contour.yaml | 59 +++++ .../{tcp_keepalive.go => socket_options.go} | 14 +- internal/envoy/v3/listener.go | 4 +- internal/envoy/v3/listener_test.go | 14 +- .../{tcp_keepalive.go => socket_options.go} | 58 ++++- internal/envoy/v3/socket_options_test.go | 61 ++++++ internal/envoy/v3/stats.go | 12 +- internal/envoy/v3/stats_test.go | 14 +- .../featuretests/v3/authorization_test.go | 8 +- .../v3/downstreamvalidation_test.go | 16 +- internal/featuretests/v3/envoy.go | 2 +- internal/featuretests/v3/fallbackcert_test.go | 8 +- .../v3/global_authorization_test.go | 8 +- internal/featuretests/v3/httproute_test.go | 2 +- .../featuretests/v3/jwtverification_test.go | 28 +-- internal/featuretests/v3/listeners_test.go | 32 +-- internal/featuretests/v3/routeweight_test.go | 12 +- internal/featuretests/v3/tcpproxy_test.go | 16 +- internal/featuretests/v3/tcproute_test.go | 8 +- .../v3/tlscertificatedelegation_test.go | 2 +- .../v3/tlsprotocolversion_test.go | 4 +- internal/featuretests/v3/tlsroute_test.go | 10 +- internal/featuretests/v3/wildcardhost_test.go | 2 +- internal/xdscache/v3/listener.go | 11 + internal/xdscache/v3/listener_test.go | 203 +++++++++++------- pkg/config/parameters.go | 34 +++ pkg/config/parameters_test.go | 15 ++ .../docs/main/config/api-reference.html | 65 ++++++ site/content/docs/main/configuration.md | 14 ++ 40 files changed, 829 insertions(+), 191 deletions(-) create mode 100644 changelogs/unreleased/5352-tsaarni-small.md rename internal/envoy/{tcp_keepalive.go => socket_options.go} (65%) rename internal/envoy/v3/{tcp_keepalive.go => socket_options.go} (59%) create mode 100644 internal/envoy/v3/socket_options_test.go diff --git a/apis/projectcontour/v1alpha1/contourconfig.go b/apis/projectcontour/v1alpha1/contourconfig.go index 68d8f8c377a..5699d5e1f30 100644 --- a/apis/projectcontour/v1alpha1/contourconfig.go +++ b/apis/projectcontour/v1alpha1/contourconfig.go @@ -386,6 +386,30 @@ type EnvoyListenerConfig struct { // TLS holds various configurable Envoy TLS listener values. // +optional TLS *EnvoyTLS `json:"tls,omitempty"` + + // SocketOptions defines configurable socket options for the listeners. + // Single set of options are applied to all listeners. + // +optional + SocketOptions *SocketOptions `json:"socketOptions,omitempty"` +} + +// SocketOptions defines configurable socket options for Envoy listeners. +type SocketOptions struct { + // Defines the value for IPv4 TOS field (including 6 bit DSCP field) for IP packets originating from Envoy listeners. + // Single value is applied to all listeners. + // If listeners are bound to IPv6-only addresses, setting this option will cause an error. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=255 + // +optional + TOS int32 `json:"tos,omitempty"` + + // Defines the value for IPv6 Traffic Class field (including 6 bit DSCP field) for IP packets originating from the Envoy listeners. + // Single value is applied to all listeners. + // If listeners are bound to IPv4-only addresses, setting this option will cause an error. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=255 + // +optional + TrafficClass int32 `json:"trafficClass,omitempty"` } // EnvoyTLS describes tls parameters for Envoy listneners. diff --git a/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go b/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go index a0180e31da0..be84902ad84 100644 --- a/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go +++ b/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go @@ -578,6 +578,11 @@ func (in *EnvoyListenerConfig) DeepCopyInto(out *EnvoyListenerConfig) { *out = new(EnvoyTLS) (*in).DeepCopyInto(*out) } + if in.SocketOptions != nil { + in, out := &in.SocketOptions, &out.SocketOptions + *out = new(SocketOptions) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyListenerConfig. @@ -1127,6 +1132,21 @@ func (in *RateLimitServiceConfig) DeepCopy() *RateLimitServiceConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SocketOptions) DeepCopyInto(out *SocketOptions) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SocketOptions. +func (in *SocketOptions) DeepCopy() *SocketOptions { + if in == nil { + return nil + } + out := new(SocketOptions) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLS) DeepCopyInto(out *TLS) { *out = *in diff --git a/changelogs/unreleased/5352-tsaarni-small.md b/changelogs/unreleased/5352-tsaarni-small.md new file mode 100644 index 00000000000..b9b971c7e94 --- /dev/null +++ b/changelogs/unreleased/5352-tsaarni-small.md @@ -0,0 +1 @@ +Add configuration for socket options to support DSCP marking for outbound IP packets, for both IPv4 (TOS field) and IPv6 (Traffic Class field). diff --git a/cmd/contour/serve.go b/cmd/contour/serve.go index 4a5e6108fb6..273834e5a6f 100644 --- a/cmd/contour/serve.go +++ b/cmd/contour/serve.go @@ -423,6 +423,7 @@ func (s *Server) doServe() error { ConnectionBalancer: contourConfiguration.Envoy.Listener.ConnectionBalancer, MaxRequestsPerConnection: contourConfiguration.Envoy.Listener.MaxRequestsPerConnection, PerConnectionBufferLimitBytes: contourConfiguration.Envoy.Listener.PerConnectionBufferLimitBytes, + SocketOptions: contourConfiguration.Envoy.Listener.SocketOptions, } if listenerConfig.TracingConfig, err = s.setupTracingService(contourConfiguration.Tracing); err != nil { diff --git a/cmd/contour/servecontext.go b/cmd/contour/servecontext.go index 1ffd9997b88..629ef75280f 100644 --- a/cmd/contour/servecontext.go +++ b/cmd/contour/servecontext.go @@ -533,6 +533,10 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_api_v1alpha MaximumProtocolVersion: ctx.Config.TLS.MaximumProtocolVersion, CipherSuites: cipherSuites, }, + SocketOptions: &contour_api_v1alpha1.SocketOptions{ + TOS: ctx.Config.Listener.SocketOptions.TOS, + TrafficClass: ctx.Config.Listener.SocketOptions.TrafficClass, + }, }, Service: &contour_api_v1alpha1.NamespacedName{ Name: ctx.Config.EnvoyServiceName, diff --git a/cmd/contour/servecontext_test.go b/cmd/contour/servecontext_test.go index cc714e565e5..1e7cc21db2a 100644 --- a/cmd/contour/servecontext_test.go +++ b/cmd/contour/servecontext_test.go @@ -413,6 +413,10 @@ func TestConvertServeContext(t *testing.T) { MinimumProtocolVersion: "", MaximumProtocolVersion: "", }, + SocketOptions: &contour_api_v1alpha1.SocketOptions{ + TOS: 0, + TrafficClass: 0, + }, }, HTTPListener: &contour_api_v1alpha1.EnvoyListener{ Address: "0.0.0.0", diff --git a/examples/contour/01-contour-config.yaml b/examples/contour/01-contour-config.yaml index 75528cc1bc3..59b89005e15 100644 --- a/examples/contour/01-contour-config.yaml +++ b/examples/contour/01-contour-config.yaml @@ -177,3 +177,9 @@ data: # server-certificate-path: /path/to/server-cert.pem # server-key-path: /path/to/server-private-key.pem # ca-certificate-path: /path/to/root-ca-for-client-validation.pem + # + # listener: + # connection-balancer: exact + # socket-options: + # tos: 64 + # traffic-class: 64 diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml index ccb1d01adc4..521849733e1 100644 --- a/examples/contour/01-crds.yaml +++ b/examples/contour/01-crds.yaml @@ -224,6 +224,32 @@ spec: \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket options + for the listeners. Single set of options are applied to + all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field (including + 6 bit DSCP field) for IP packets originating from Envoy + listeners. Single value is applied to all listeners. + If listeners are bound to IPv6-only addresses, setting + this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets originating + from the Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv4-only addresses, + setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. @@ -3621,6 +3647,33 @@ spec: `pass_through` \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket + options for the listeners. Single set of options are + applied to all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field + (including 6 bit DSCP field) for IP packets originating + from Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv6-only + addresses, setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets + originating from the Envoy listeners. Single value + is applied to all listeners. If listeners are bound + to IPv4-only addresses, setting this option will + cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml index cf1cf5c2886..19c8ec72791 100644 --- a/examples/render/contour-deployment.yaml +++ b/examples/render/contour-deployment.yaml @@ -210,6 +210,12 @@ data: # server-certificate-path: /path/to/server-cert.pem # server-key-path: /path/to/server-private-key.pem # ca-certificate-path: /path/to/root-ca-for-client-validation.pem + # + # listener: + # connection-balancer: exact + # socket-options: + # tos: 64 + # traffic-class: 64 --- apiVersion: apiextensions.k8s.io/v1 @@ -437,6 +443,32 @@ spec: \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket options + for the listeners. Single set of options are applied to + all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field (including + 6 bit DSCP field) for IP packets originating from Envoy + listeners. Single value is applied to all listeners. + If listeners are bound to IPv6-only addresses, setting + this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets originating + from the Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv4-only addresses, + setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. @@ -3834,6 +3866,33 @@ spec: `pass_through` \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket + options for the listeners. Single set of options are + applied to all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field + (including 6 bit DSCP field) for IP packets originating + from Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv6-only + addresses, setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets + originating from the Envoy listeners. Single value + is applied to all listeners. If listeners are bound + to IPv4-only addresses, setting this option will + cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. diff --git a/examples/render/contour-gateway-provisioner.yaml b/examples/render/contour-gateway-provisioner.yaml index 39103148552..9b361149375 100644 --- a/examples/render/contour-gateway-provisioner.yaml +++ b/examples/render/contour-gateway-provisioner.yaml @@ -238,6 +238,32 @@ spec: \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket options + for the listeners. Single set of options are applied to + all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field (including + 6 bit DSCP field) for IP packets originating from Envoy + listeners. Single value is applied to all listeners. + If listeners are bound to IPv6-only addresses, setting + this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets originating + from the Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv4-only addresses, + setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. @@ -3635,6 +3661,33 @@ spec: `pass_through` \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket + options for the listeners. Single set of options are + applied to all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field + (including 6 bit DSCP field) for IP packets originating + from Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv6-only + addresses, setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets + originating from the Envoy listeners. Single value + is applied to all listeners. If listeners are bound + to IPv4-only addresses, setting this option will + cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. diff --git a/examples/render/contour-gateway.yaml b/examples/render/contour-gateway.yaml index aa3ee90539d..3314522261e 100644 --- a/examples/render/contour-gateway.yaml +++ b/examples/render/contour-gateway.yaml @@ -216,6 +216,12 @@ data: # server-certificate-path: /path/to/server-cert.pem # server-key-path: /path/to/server-private-key.pem # ca-certificate-path: /path/to/root-ca-for-client-validation.pem + # + # listener: + # connection-balancer: exact + # socket-options: + # tos: 64 + # traffic-class: 64 --- apiVersion: apiextensions.k8s.io/v1 @@ -443,6 +449,32 @@ spec: \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket options + for the listeners. Single set of options are applied to + all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field (including + 6 bit DSCP field) for IP packets originating from Envoy + listeners. Single value is applied to all listeners. + If listeners are bound to IPv6-only addresses, setting + this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets originating + from the Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv4-only addresses, + setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. @@ -3840,6 +3872,33 @@ spec: `pass_through` \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket + options for the listeners. Single set of options are + applied to all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field + (including 6 bit DSCP field) for IP packets originating + from Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv6-only + addresses, setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets + originating from the Envoy listeners. Single value + is applied to all listeners. If listeners are bound + to IPv4-only addresses, setting this option will + cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. diff --git a/examples/render/contour.yaml b/examples/render/contour.yaml index d542a73f2d6..1f9c8f005d8 100644 --- a/examples/render/contour.yaml +++ b/examples/render/contour.yaml @@ -210,6 +210,12 @@ data: # server-certificate-path: /path/to/server-cert.pem # server-key-path: /path/to/server-private-key.pem # ca-certificate-path: /path/to/root-ca-for-client-validation.pem + # + # listener: + # connection-balancer: exact + # socket-options: + # tos: 64 + # traffic-class: 64 --- apiVersion: apiextensions.k8s.io/v1 @@ -437,6 +443,32 @@ spec: \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket options + for the listeners. Single set of options are applied to + all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field (including + 6 bit DSCP field) for IP packets originating from Envoy + listeners. Single value is applied to all listeners. + If listeners are bound to IPv6-only addresses, setting + this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets originating + from the Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv4-only addresses, + setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. @@ -3834,6 +3866,33 @@ spec: `pass_through` \n Other values will produce an error. Contour's default is overwrite." type: string + socketOptions: + description: SocketOptions defines configurable socket + options for the listeners. Single set of options are + applied to all listeners. + properties: + tos: + description: Defines the value for IPv4 TOS field + (including 6 bit DSCP field) for IP packets originating + from Envoy listeners. Single value is applied to + all listeners. If listeners are bound to IPv6-only + addresses, setting this option will cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + trafficClass: + description: Defines the value for IPv6 Traffic Class + field (including 6 bit DSCP field) for IP packets + originating from the Envoy listeners. Single value + is applied to all listeners. If listeners are bound + to IPv4-only addresses, setting this option will + cause an error. + format: int32 + maximum: 255 + minimum: 0 + type: integer + type: object tls: description: TLS holds various configurable Envoy TLS listener values. diff --git a/internal/envoy/tcp_keepalive.go b/internal/envoy/socket_options.go similarity index 65% rename from internal/envoy/tcp_keepalive.go rename to internal/envoy/socket_options.go index 9c1bd3fe867..775d605b1fb 100644 --- a/internal/envoy/tcp_keepalive.go +++ b/internal/envoy/socket_options.go @@ -15,20 +15,26 @@ package envoy import "syscall" -// We only support Envoy on Linux so always configure Linux TCP keep-alive -// socket options regardless of the platform that Contour is running on. // nolint:revive const ( + // We only support Envoy on Linux so always configure Linux TCP keep-alive + // socket options regardless of the platform that Contour is running on (e.g. Contour on macOS + Envoy on Linux). TCP_KEEPIDLE = 0x4 // Linux syscall.TCP_KEEPIDLE TCP_KEEPINTVL = 0x5 // Linux syscall.TCP_KEEPINTVL TCP_KEEPCNT = 0x6 // Linux syscall.TCP_KEEPCNT + // The following are for setting DSCP values on Linux. + IP_TOS = 0x1 // Linux syscall.IP_TOS + IPV6_TCLASS = 0x43 // Linux syscall.IPV6_TCLASS + // The following are Linux syscall constants for all // architectures except MIPS. SOL_SOCKET = 0x1 SO_KEEPALIVE = 0x9 - // IPPROTO_TCP has the same value across Go platforms, but + // IPPROTO_* has the same value across Go platforms, but // is defined here for consistency. - IPPROTO_TCP = syscall.IPPROTO_TCP + IPPROTO_IP = syscall.IPPROTO_IP + IPPROTO_IPV6 = syscall.IPPROTO_IPV6 + IPPROTO_TCP = syscall.IPPROTO_TCP ) diff --git a/internal/envoy/v3/listener.go b/internal/envoy/v3/listener.go index f24a3a19a17..2707700875a 100644 --- a/internal/envoy/v3/listener.go +++ b/internal/envoy/v3/listener.go @@ -130,12 +130,12 @@ func ProxyProtocol() *envoy_listener_v3.ListenerFilter { } // Listener returns a new envoy_listener_v3.Listener for the supplied address, port, and filters. -func Listener(name, address string, port int, perConnectionBufferLimitBytes *uint32, lf []*envoy_listener_v3.ListenerFilter, filters ...*envoy_listener_v3.Filter) *envoy_listener_v3.Listener { +func Listener(name, address string, port int, perConnectionBufferLimitBytes *uint32, so *SocketOptions, lf []*envoy_listener_v3.ListenerFilter, filters ...*envoy_listener_v3.Filter) *envoy_listener_v3.Listener { l := &envoy_listener_v3.Listener{ Name: name, Address: SocketAddress(address, port), ListenerFilters: lf, - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: so.Build(), } if perConnectionBufferLimitBytes != nil { diff --git a/internal/envoy/v3/listener_test.go b/internal/envoy/v3/listener_test.go index ece9eb4efc0..4a9d8046e56 100644 --- a/internal/envoy/v3/listener_test.go +++ b/internal/envoy/v3/listener_test.go @@ -100,7 +100,7 @@ func TestListener(t *testing.T) { FilterChains: FilterChains( HTTPConnectionManager("http", FileAccessLogEnvoy("/dev/null", "", nil, v1alpha1.LogLevelInfo), 0), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, }, "insecure listener w/ proxy": { @@ -122,7 +122,7 @@ func TestListener(t *testing.T) { FilterChains: FilterChains( HTTPConnectionManager("http-proxy", FileAccessLogEnvoy("/dev/null", "", nil, v1alpha1.LogLevelInfo), 0), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, }, "secure listener": { @@ -138,7 +138,7 @@ func TestListener(t *testing.T) { ListenerFilters: ListenerFilters( TLSInspector(), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, }, "secure listener w/ proxy": { @@ -156,7 +156,7 @@ func TestListener(t *testing.T) { ProxyProtocol(), TLSInspector(), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, }, "listener w/ connection buffer limits": { @@ -174,7 +174,7 @@ func TestListener(t *testing.T) { FilterChains: FilterChains( HTTPConnectionManager("http", FileAccessLogEnvoy("/dev/null", "", nil, v1alpha1.LogLevelInfo), 0), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, }, "secure listener w/ connection buffer limits": { @@ -192,14 +192,14 @@ func TestListener(t *testing.T) { ListenerFilters: ListenerFilters( TLSInspector(), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { - got := Listener(tc.name, tc.address, tc.port, tc.perConnectionBufferLimitBytes, tc.lf, tc.f...) + got := Listener(tc.name, tc.address, tc.port, tc.perConnectionBufferLimitBytes, NewSocketOptions().TCPKeepalive(), tc.lf, tc.f...) protobuf.ExpectEqual(t, tc.want, got) }) } diff --git a/internal/envoy/v3/tcp_keepalive.go b/internal/envoy/v3/socket_options.go similarity index 59% rename from internal/envoy/v3/tcp_keepalive.go rename to internal/envoy/v3/socket_options.go index fed30a22cee..a2b583f1070 100644 --- a/internal/envoy/v3/tcp_keepalive.go +++ b/internal/envoy/v3/socket_options.go @@ -18,14 +18,18 @@ import ( "github.com/projectcontour/contour/internal/envoy" ) -func TCPKeepaliveSocketOptions() []*envoy_core_v3.SocketOption { +type SocketOptions struct { + options []*envoy_core_v3.SocketOption +} + +func NewSocketOptions() *SocketOptions { + return &SocketOptions{} +} - // Note: TCP_KEEPIDLE + (TCP_KEEPINTVL * TCP_KEEPCNT) must be greater than - // the grpc.KeepaliveParams time + timeout (currently 60 + 20 = 80 seconds) - // otherwise TestGRPC/StreamClusters fails. - return []*envoy_core_v3.SocketOption{ +func (so *SocketOptions) TCPKeepalive() *SocketOptions { + so.options = append(so.options, // Enable TCP keep-alive. - { + &envoy_core_v3.SocketOption{ Description: "Enable TCP keep-alive", Level: envoy.SOL_SOCKET, Name: envoy.SO_KEEPALIVE, @@ -34,7 +38,7 @@ func TCPKeepaliveSocketOptions() []*envoy_core_v3.SocketOption { }, // The time (in seconds) the connection needs to remain idle // before TCP starts sending keepalive probes. - { + &envoy_core_v3.SocketOption{ Description: "TCP keep-alive initial idle time", Level: envoy.IPPROTO_TCP, Name: envoy.TCP_KEEPIDLE, @@ -42,7 +46,7 @@ func TCPKeepaliveSocketOptions() []*envoy_core_v3.SocketOption { State: envoy_core_v3.SocketOption_STATE_LISTENING, }, // The time (in seconds) between individual keepalive probes. - { + &envoy_core_v3.SocketOption{ Description: "TCP keep-alive time between probes", Level: envoy.IPPROTO_TCP, Name: envoy.TCP_KEEPINTVL, @@ -52,12 +56,48 @@ func TCPKeepaliveSocketOptions() []*envoy_core_v3.SocketOption { // The maximum number of TCP keep-alive probes to send before // giving up and killing the connection if no response is // obtained from the other end. - { + &envoy_core_v3.SocketOption{ Description: "TCP keep-alive probe count", Level: envoy.IPPROTO_TCP, Name: envoy.TCP_KEEPCNT, Value: &envoy_core_v3.SocketOption_IntValue{IntValue: 9}, State: envoy_core_v3.SocketOption_STATE_LISTENING, }, + ) + + return so +} + +// TOS sets the IP_TOS socket option for IPv4 socket. +func (so *SocketOptions) TOS(value int32) *SocketOptions { + if value != 0 { + so.options = append(so.options, + &envoy_core_v3.SocketOption{ + Description: "Set IPv4 TOS field", + Level: envoy.IPPROTO_IP, + Name: envoy.IP_TOS, + State: envoy_core_v3.SocketOption_STATE_LISTENING, + Value: &envoy_core_v3.SocketOption_IntValue{IntValue: int64(value)}, + }) } + return so +} + +// TrafficClass sets the IPV6_TCLASS socket option for IPv4 socket. +func (so *SocketOptions) TrafficClass(value int32) *SocketOptions { + if value != 0 { + so.options = append(so.options, + &envoy_core_v3.SocketOption{ + Description: "Set IPv6 Traffic Class field", + Level: envoy.IPPROTO_IPV6, + Name: envoy.IPV6_TCLASS, + State: envoy_core_v3.SocketOption_STATE_LISTENING, + Value: &envoy_core_v3.SocketOption_IntValue{IntValue: int64(value)}, + }) + } + return so +} + +func (so *SocketOptions) Build() []*envoy_core_v3.SocketOption { + return so.options } diff --git a/internal/envoy/v3/socket_options_test.go b/internal/envoy/v3/socket_options_test.go new file mode 100644 index 00000000000..689fe2af015 --- /dev/null +++ b/internal/envoy/v3/socket_options_test.go @@ -0,0 +1,61 @@ +// Copyright Project Contour Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v3 + +import ( + "testing" + + envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + "github.com/projectcontour/contour/internal/envoy" + "github.com/stretchr/testify/assert" +) + +func TestSocketOptions(t *testing.T) { + // No options shall be set when value 0 is set. + so := NewSocketOptions().TOS(0).TrafficClass(0) + assert.Equal(t, len(so.options), 0) + + so.TOS(64) + assert.Equal(t, so.Build(), + []*envoy_core_v3.SocketOption{ + { + Description: "Set IPv4 TOS field", + Level: envoy.IPPROTO_IP, + Name: envoy.IP_TOS, + Value: &envoy_core_v3.SocketOption_IntValue{IntValue: 64}, + State: envoy_core_v3.SocketOption_STATE_LISTENING, + }, + }, + ) + + so.TrafficClass(64) + assert.Equal(t, so.Build(), + []*envoy_core_v3.SocketOption{ + { + Description: "Set IPv4 TOS field", + Level: envoy.IPPROTO_IP, + Name: envoy.IP_TOS, + Value: &envoy_core_v3.SocketOption_IntValue{IntValue: 64}, + State: envoy_core_v3.SocketOption_STATE_LISTENING, + }, + { + Description: "Set IPv6 Traffic Class field", + Level: envoy.IPPROTO_IPV6, + Name: envoy.IPV6_TCLASS, + Value: &envoy_core_v3.SocketOption_IntValue{IntValue: 64}, + State: envoy_core_v3.SocketOption_STATE_LISTENING, + }, + }, + ) +} diff --git a/internal/envoy/v3/stats.go b/internal/envoy/v3/stats.go index 179500e9c1d..a6395e82491 100644 --- a/internal/envoy/v3/stats.go +++ b/internal/envoy/v3/stats.go @@ -43,14 +43,14 @@ func StatsListeners(metrics contour_api_v1alpha1.MetricsConfig, health contour_a listeners = []*envoy_listener_v3.Listener{{ Name: "stats", Address: SocketAddress(metrics.Address, metrics.Port), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), FilterChains: filterChain("stats", DownstreamTLSTransportSocket( downstreamTLSContext(metrics.TLS.CAFile != "")), routeForAdminInterface("/stats")), }, { Name: "health", Address: SocketAddress(health.Address, health.Port), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), FilterChains: filterChain("stats", nil, routeForAdminInterface("/ready")), }} @@ -60,7 +60,7 @@ func StatsListeners(metrics contour_api_v1alpha1.MetricsConfig, health contour_a listeners = []*envoy_listener_v3.Listener{{ Name: "stats-health", Address: SocketAddress(metrics.Address, metrics.Port), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), FilterChains: filterChain("stats", nil, routeForAdminInterface("/ready", "/stats")), }} @@ -69,12 +69,12 @@ func StatsListeners(metrics contour_api_v1alpha1.MetricsConfig, health contour_a listeners = []*envoy_listener_v3.Listener{{ Name: "stats", Address: SocketAddress(metrics.Address, metrics.Port), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), FilterChains: filterChain("stats", nil, routeForAdminInterface("/stats")), }, { Name: "health", Address: SocketAddress(health.Address, health.Port), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), FilterChains: filterChain("stats", nil, routeForAdminInterface("/ready")), }} } @@ -103,7 +103,7 @@ func AdminListener(port int) *envoy_listener_v3.Listener { "/stats/recentlookups", ), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), } } diff --git a/internal/envoy/v3/stats_test.go b/internal/envoy/v3/stats_test.go index 2ab95c1e42d..9fea6e9f02f 100644 --- a/internal/envoy/v3/stats_test.go +++ b/internal/envoy/v3/stats_test.go @@ -106,7 +106,7 @@ func TestStatsListeners(t *testing.T) { }, }, ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }}}) run(t, "stats-over-https-and-health-over-http", testcase{ @@ -164,7 +164,7 @@ func TestStatsListeners(t *testing.T) { }, ), }}, - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, { Name: "health", Address: SocketAddress("127.0.0.127", 8124), @@ -194,7 +194,7 @@ func TestStatsListeners(t *testing.T) { }, }, ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }}}) run(t, "stats-over-https-with-client-auth-and-health-over-http", testcase{ @@ -260,7 +260,7 @@ func TestStatsListeners(t *testing.T) { }, ), }}, - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, { Name: "health", Address: SocketAddress("127.0.0.127", 8124), @@ -290,7 +290,7 @@ func TestStatsListeners(t *testing.T) { }, }, ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }}}) run(t, "stats-and-health-over-http-but-different-listeners", testcase{ @@ -330,7 +330,7 @@ func TestStatsListeners(t *testing.T) { }, }, ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, { Name: "health", Address: SocketAddress("127.0.0.128", 8124), @@ -360,7 +360,7 @@ func TestStatsListeners(t *testing.T) { }, }, ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }}}) } diff --git a/internal/featuretests/v3/authorization_test.go b/internal/featuretests/v3/authorization_test.go index c2ad0124f66..3e51070cba2 100644 --- a/internal/featuretests/v3/authorization_test.go +++ b/internal/featuretests/v3/authorization_test.go @@ -106,7 +106,7 @@ func authzResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c *Conto ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener()), @@ -193,7 +193,7 @@ func authzFailOpen(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener()), }).Status(p).IsValid() @@ -508,7 +508,7 @@ func authzInvalidReference(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener()), }).Status(invalid).IsValid() @@ -577,7 +577,7 @@ func authzWithRequestBodyBufferSettings(t *testing.T, rh ResourceEventHandlerWra ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener()), }).Status(p).IsValid() diff --git a/internal/featuretests/v3/downstreamvalidation_test.go b/internal/featuretests/v3/downstreamvalidation_test.go index 0499c922253..d82744eca5b 100644 --- a/internal/featuretests/v3/downstreamvalidation_test.go +++ b/internal/featuretests/v3/downstreamvalidation_test.go @@ -96,7 +96,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -144,7 +144,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -195,7 +195,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -260,7 +260,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, @@ -313,7 +313,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, @@ -362,7 +362,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, @@ -422,7 +422,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, @@ -476,7 +476,7 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, diff --git a/internal/featuretests/v3/envoy.go b/internal/featuretests/v3/envoy.go index ea60b26ef1b..a7f74e08ac2 100644 --- a/internal/featuretests/v3/envoy.go +++ b/internal/featuretests/v3/envoy.go @@ -597,6 +597,6 @@ func defaultHTTPListener() *envoy_listener_v3.Listener { FilterChains: envoy_v3.FilterChains( envoy_v3.HTTPConnectionManager("ingress_http", envoy_v3.FileAccessLogEnvoy("/dev/stdout", "", nil, contour_api_v1alpha1.LogLevelInfo), 0), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } } diff --git a/internal/featuretests/v3/fallbackcert_test.go b/internal/featuretests/v3/fallbackcert_test.go index 07cbfa56571..bcef7c82d56 100644 --- a/internal/featuretests/v3/fallbackcert_test.go +++ b/internal/featuretests/v3/fallbackcert_test.go @@ -107,7 +107,7 @@ func TestFallbackCertificate(t *testing.T) { httpsFilterFor("fallback.example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -170,7 +170,7 @@ func TestFallbackCertificate(t *testing.T) { nil, "h2", "http/1.1"), filterchaintlsfallback(fallbackSecret, nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -212,7 +212,7 @@ func TestFallbackCertificate(t *testing.T) { nil, "h2", "http/1.1"), filterchaintlsfallback(fallbackSecret, nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -284,7 +284,7 @@ func TestFallbackCertificate(t *testing.T) { nil, "h2", "http/1.1"), filterchaintlsfallback(fallbackSecret, nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) diff --git a/internal/featuretests/v3/global_authorization_test.go b/internal/featuretests/v3/global_authorization_test.go index c600464a8de..d928bc2057e 100644 --- a/internal/featuretests/v3/global_authorization_test.go +++ b/internal/featuretests/v3/global_authorization_test.go @@ -134,7 +134,7 @@ func globalExternalAuthorizationFilterExistsTLS(t *testing.T, rh ResourceEventHa ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -197,7 +197,7 @@ func globalExternalAuthorizationWithTLSGlobalAuthDisabled(t *testing.T, rh Resou httpsFilterFor("foo.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -346,7 +346,7 @@ func globalExternalAuthorizationWithMergedAuthPolicyTLS(t *testing.T, rh Resourc ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -473,7 +473,7 @@ func globalExternalAuthorizationWithTLSAuthOverride(t *testing.T, rh ResourceEve ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ diff --git a/internal/featuretests/v3/httproute_test.go b/internal/featuretests/v3/httproute_test.go index 35746900060..974660eb8bd 100644 --- a/internal/featuretests/v3/httproute_test.go +++ b/internal/featuretests/v3/httproute_test.go @@ -180,7 +180,7 @@ func TestGateway_TLS(t *testing.T) { httpsFilterForGateway("https-443", "test.projectcontour.io"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) diff --git a/internal/featuretests/v3/jwtverification_test.go b/internal/featuretests/v3/jwtverification_test.go index bc6ee7a0814..c3ba34337b3 100644 --- a/internal/featuretests/v3/jwtverification_test.go +++ b/internal/featuretests/v3/jwtverification_test.go @@ -90,7 +90,7 @@ func TestJWTVerification(t *testing.T) { filterchaintls("jwt.example.com", sec1, httpsFilterFor("jwt.example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -168,7 +168,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(clusterType, "dnsname/https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -321,7 +321,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(routeType, "https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -429,7 +429,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(routeType, "https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -559,7 +559,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(routeType, "https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -653,7 +653,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(clusterType, "dnsname/https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -807,7 +807,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(clusterType, "dnsname/https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -971,7 +971,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(clusterType, "dnsname/https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -1117,7 +1117,7 @@ func TestJWTVerification(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(clusterType, "dnsname/https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -1250,7 +1250,7 @@ func TestJWTVerification_Inclusion(t *testing.T) { filterchaintls("jwt.example.com", sec1, httpsFilterFor("jwt.example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -1338,7 +1338,7 @@ func TestJWTVerification_Inclusion(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(clusterType, "dnsname/https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -1501,7 +1501,7 @@ func TestJWTVerification_Inclusion(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(routeType, "https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -1619,7 +1619,7 @@ func TestJWTVerification_Inclusion(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(routeType, "https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -1759,7 +1759,7 @@ func TestJWTVerification_Inclusion(t *testing.T) { }), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }).Request(routeType, "https/jwt.example.com").Equals(&envoy_discovery_v3.DiscoveryResponse{ diff --git a/internal/featuretests/v3/listeners_test.go b/internal/featuretests/v3/listeners_test.go index efee21d861a..c3fae12cc50 100644 --- a/internal/featuretests/v3/listeners_test.go +++ b/internal/featuretests/v3/listeners_test.go @@ -212,7 +212,7 @@ func TestTLSListener(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -257,7 +257,7 @@ func TestTLSListener(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -367,7 +367,7 @@ func TestHTTPProxyTLSListener(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } // add service @@ -417,7 +417,7 @@ func TestHTTPProxyTLSListener(t *testing.T) { envoy_v3.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } // add ingress and assert the existence of ingress_http and ingres_https @@ -500,7 +500,7 @@ func TestTLSListenerCipherSuites(t *testing.T) { envoy_v3.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } // add service @@ -579,7 +579,7 @@ func TestLDSFilter(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), TypeUrl: listenerType, @@ -737,7 +737,7 @@ func TestLDSIngressHTTPSUseProxyProtocol(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, @@ -833,7 +833,7 @@ func TestLDSCustomAddressAndPort(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, @@ -927,7 +927,7 @@ func TestLDSCustomAccessLogPaths(t *testing.T) { Get(), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ VersionInfo: "1", @@ -1013,7 +1013,7 @@ func TestHTTPProxyHTTPS(t *testing.T) { httpsFilterFor("example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ VersionInfo: "1", @@ -1093,7 +1093,7 @@ func TestHTTPProxyTLSVersion(t *testing.T) { envoy_v3.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } // verify that p1's TLS 1.1 minimum has been upgraded to 1.2 @@ -1151,7 +1151,7 @@ func TestHTTPProxyTLSVersion(t *testing.T) { envoy_v3.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } // verify that p2's TLS 1.3 minimum has NOT been downgraded to 1.2 @@ -1479,7 +1479,7 @@ func TestGatewayListenersSetAddress(t *testing.T) { Name: "http-80", Address: envoy_v3.SocketAddress("127.0.0.100", 8080), FilterChains: envoy_v3.FilterChains(httpFilterForGateway()), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -1499,7 +1499,7 @@ func TestGatewayListenersSetAddress(t *testing.T) { httpsFilterForGateway("https-443", "test.projectcontour.io"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -1522,7 +1522,7 @@ func TestGatewayListenersSetAddress(t *testing.T) { tcpproxy("https-8443", "default/svc1/80/da39a3ee5e"), ), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -1538,7 +1538,7 @@ func TestGatewayListenersSetAddress(t *testing.T) { tcpproxy("tcp-27017", "default/svc1/80/da39a3ee5e"), ), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), TypeUrl: listenerType, diff --git a/internal/featuretests/v3/routeweight_test.go b/internal/featuretests/v3/routeweight_test.go index 16770c995ff..b62a9cad300 100644 --- a/internal/featuretests/v3/routeweight_test.go +++ b/internal/featuretests/v3/routeweight_test.go @@ -145,7 +145,7 @@ func TestHTTPProxy_TCPProxyWithAServiceWeight(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -201,7 +201,7 @@ func TestHTTPProxy_TCPProxyWithAServiceWeight(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -257,7 +257,7 @@ func TestHTTPProxy_TCPProxyWithAServiceWeight(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -314,7 +314,7 @@ func TestHTTPProxy_TCPProxyWithAServiceWeight(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -531,7 +531,7 @@ func TestTLSRoute_RouteWithAServiceWeight(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -585,7 +585,7 @@ func TestTLSRoute_RouteWithAServiceWeight(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), diff --git a/internal/featuretests/v3/tcpproxy_test.go b/internal/featuretests/v3/tcpproxy_test.go index 624a6b0dcb3..29150fe633b 100644 --- a/internal/featuretests/v3/tcpproxy_test.go +++ b/internal/featuretests/v3/tcpproxy_test.go @@ -97,7 +97,7 @@ func TestTCPProxy(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -193,7 +193,7 @@ func TestTCPProxyDelegation(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -277,7 +277,7 @@ func TestTCPProxyTLSPassthrough(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -362,7 +362,7 @@ func TestTCPProxyTLSBackend(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -454,7 +454,7 @@ func TestTCPProxyAndHTTPService(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -544,7 +544,7 @@ func TestTCPProxyAndHTTPServicePermitInsecure(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -632,7 +632,7 @@ func TestTCPProxyTLSPassthroughAndHTTPService(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -721,7 +721,7 @@ func TestTCPProxyTLSPassthroughAndHTTPServicePermitInsecure(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), diff --git a/internal/featuretests/v3/tcproute_test.go b/internal/featuretests/v3/tcproute_test.go index 1519a3d8eb8..58532415269 100644 --- a/internal/featuretests/v3/tcproute_test.go +++ b/internal/featuretests/v3/tcproute_test.go @@ -108,7 +108,7 @@ func TestTCPRoute(t *testing.T) { tcpproxy("tcp-10000", "default/backend-1/80/da39a3ee5e"), ), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), TypeUrl: listenerType, @@ -159,7 +159,7 @@ func TestTCPRoute(t *testing.T) { tcpproxy("tcp-10000", "default/backend-1/80/da39a3ee5e"), ), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: "tcp-10001", @@ -169,7 +169,7 @@ func TestTCPRoute(t *testing.T) { tcpproxy("tcp-10001", "default/backend-2/80/da39a3ee5e"), ), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), TypeUrl: listenerType, @@ -270,7 +270,7 @@ func TestTCPRoute_TLSTermination(t *testing.T) { FilterChains: appendFilterChains( filterchaintls("*", sec1, tcpproxy("https-5000", "default/backend-1/80/da39a3ee5e"), nil), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), diff --git a/internal/featuretests/v3/tlscertificatedelegation_test.go b/internal/featuretests/v3/tlscertificatedelegation_test.go index 905fe559632..16aefeb1774 100644 --- a/internal/featuretests/v3/tlscertificatedelegation_test.go +++ b/internal/featuretests/v3/tlscertificatedelegation_test.go @@ -111,7 +111,7 @@ func TestTLSCertificateDelegation(t *testing.T) { httpsFilterFor("example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ diff --git a/internal/featuretests/v3/tlsprotocolversion_test.go b/internal/featuretests/v3/tlsprotocolversion_test.go index 2f244e3a5e4..b05334ffb5e 100644 --- a/internal/featuretests/v3/tlsprotocolversion_test.go +++ b/internal/featuretests/v3/tlsprotocolversion_test.go @@ -81,7 +81,7 @@ func TestTLSProtocolVersion(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), TypeUrl: listenerType, @@ -142,7 +142,7 @@ func TestTLSProtocolVersion(t *testing.T) { envoy_v3.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType, "ingress_https").Equals(&envoy_discovery_v3.DiscoveryResponse{ diff --git a/internal/featuretests/v3/tlsroute_test.go b/internal/featuretests/v3/tlsroute_test.go index 0621ddcd65f..056bfa43003 100644 --- a/internal/featuretests/v3/tlsroute_test.go +++ b/internal/featuretests/v3/tlsroute_test.go @@ -114,7 +114,7 @@ func TestTLSRoute_TLSPassthrough(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -157,7 +157,7 @@ func TestTLSRoute_TLSPassthrough(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -224,7 +224,7 @@ func TestTLSRoute_TLSPassthrough(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -328,7 +328,7 @@ func TestTLSRoute_TLSTermination(t *testing.T) { FilterChains: appendFilterChains( filterchaintls("test1.projectcontour.io", sec1, tcpproxy("https-5000", "default/svc1/80/da39a3ee5e"), nil), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) @@ -366,7 +366,7 @@ func TestTLSRoute_TLSTermination(t *testing.T) { filterchaintls("test1.projectcontour.io", sec1, tcpproxy("https-5000", "default/svc1/80/da39a3ee5e"), nil), filterchaintls("test2.projectcontour.io", sec1, tcpproxy("https-5000", "default/svc2/80/da39a3ee5e"), nil), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), }) diff --git a/internal/featuretests/v3/wildcardhost_test.go b/internal/featuretests/v3/wildcardhost_test.go index 53aeae1f079..0d0d575c132 100644 --- a/internal/featuretests/v3/wildcardhost_test.go +++ b/internal/featuretests/v3/wildcardhost_test.go @@ -237,7 +237,7 @@ func TestIngressWildcardHostHTTPSWildcardSecret(t *testing.T) { httpsFilterFor("*.foo-tls.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), diff --git a/internal/xdscache/v3/listener.go b/internal/xdscache/v3/listener.go index 08f77fa82e9..c9cf6d04aaf 100644 --- a/internal/xdscache/v3/listener.go +++ b/internal/xdscache/v3/listener.go @@ -144,6 +144,9 @@ type ListenerConfig struct { // TracingConfig optionally configures the tracing collector Service to be // used. TracingConfig *TracingConfig + + // SocketOptions configures socket options HTTP and HTTPS listeners. + SocketOptions *contour_api_v1alpha1.SocketOptions } type ExtensionServiceConfig struct { @@ -374,6 +377,11 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { return b } + socketOptions := envoy_v3.NewSocketOptions().TCPKeepalive() + if cfg.SocketOptions != nil { + socketOptions = socketOptions.TOS(cfg.SocketOptions.TOS).TrafficClass(cfg.SocketOptions.TrafficClass) + } + for _, listener := range root.Listeners { // A Listener-level TCPProxy proxies all traffic for // the Listener port, i.e. no filter chain match. @@ -383,6 +391,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { listener.Address, listener.Port, cfg.PerConnectionBufferLimitBytes, + socketOptions, nil, envoy_v3.TCPProxy(listener.Name, listener.TCPProxy, cfg.newInsecureAccessLog()), ) @@ -422,6 +431,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { listener.Address, listener.Port, cfg.PerConnectionBufferLimitBytes, + socketOptions, proxyProtocol(cfg.UseProxyProto), cm, ) @@ -436,6 +446,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { listener.Address, listener.Port, cfg.PerConnectionBufferLimitBytes, + socketOptions, secureProxyProtocol(cfg.UseProxyProto), ) } diff --git a/internal/xdscache/v3/listener_test.go b/internal/xdscache/v3/listener_test.go index e6025561663..280401a7aa2 100644 --- a/internal/xdscache/v3/listener_test.go +++ b/internal/xdscache/v3/listener_test.go @@ -58,14 +58,14 @@ func TestListenerCacheContents(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), want: []proto.Message{ &envoy_listener_v3.Listener{ Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, }, }, @@ -92,7 +92,7 @@ func TestListenerCacheQuery(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), query: []string{ENVOY_HTTP_LISTENER}, want: []proto.Message{ @@ -100,7 +100,7 @@ func TestListenerCacheQuery(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, }, }, @@ -109,7 +109,7 @@ func TestListenerCacheQuery(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), query: []string{ENVOY_HTTP_LISTENER, "stats-listener"}, want: []proto.Message{ @@ -117,7 +117,7 @@ func TestListenerCacheQuery(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, }, }, @@ -126,7 +126,7 @@ func TestListenerCacheQuery(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), query: []string{"stats-listener"}, want: nil, @@ -201,7 +201,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "one http only httpproxy": { @@ -244,7 +244,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -298,7 +298,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -312,7 +312,7 @@ func TestListenerVisit(t *testing.T) { TransportSocket: transportSocket("secret", envoy_tls_v3.TlsParameters_TLSv1_2, envoy_tls_v3.TlsParameters_TLSv1_3, nil, "h2", "http/1.1"), Filters: envoy_v3.Filters(httpsFilterFor("whatever.example.com")), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -388,7 +388,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -408,7 +408,7 @@ func TestListenerVisit(t *testing.T) { TransportSocket: transportSocket("secret", envoy_tls_v3.TlsParameters_TLSv1_2, envoy_tls_v3.TlsParameters_TLSv1_3, nil, "h2", "http/1.1"), Filters: envoy_v3.Filters(httpsFilterFor("sortedsecond.example.com")), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -462,7 +462,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "simple httpproxy with secret": { @@ -513,7 +513,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -527,7 +527,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -610,7 +610,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "use proxy proto": { @@ -669,7 +669,7 @@ func TestListenerVisit(t *testing.T) { envoy_v3.ProxyProtocol(), ), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -684,7 +684,7 @@ func TestListenerVisit(t *testing.T) { TransportSocket: transportSocket("secret", envoy_tls_v3.TlsParameters_TLSv1_2, envoy_tls_v3.TlsParameters_TLSv1_3, nil, "h2", "http/1.1"), Filters: envoy_v3.Filters(httpsFilterFor("whatever.example.com")), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -742,7 +742,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy("/tmp/http_access.log", "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -762,7 +762,7 @@ func TestListenerVisit(t *testing.T) { AccessLoggers(envoy_v3.FileAccessLogEnvoy("/tmp/https_access.log", "", nil, v1alpha1.LogLevelInfo)). Get()), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -820,7 +820,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -834,7 +834,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -896,7 +896,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -910,7 +910,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -968,7 +968,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1053,7 +1053,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "tls-cipher-suites from config": { @@ -1110,7 +1110,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1124,7 +1124,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -1205,7 +1205,7 @@ func TestListenerVisit(t *testing.T) { RequestTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1241,7 +1241,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -1322,7 +1322,7 @@ func TestListenerVisit(t *testing.T) { ConnectionIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1358,7 +1358,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -1439,7 +1439,7 @@ func TestListenerVisit(t *testing.T) { StreamIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1475,7 +1475,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -1556,7 +1556,7 @@ func TestListenerVisit(t *testing.T) { DelayedCloseTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1592,7 +1592,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -1673,7 +1673,7 @@ func TestListenerVisit(t *testing.T) { MaxConnectionDuration(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1709,7 +1709,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -1790,7 +1790,7 @@ func TestListenerVisit(t *testing.T) { ConnectionShutdownGracePeriod(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1826,7 +1826,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with fallback certificate": { @@ -1894,7 +1894,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -1915,7 +1915,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "multiple httpproxies with fallback certificate": { @@ -2008,7 +2008,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -2038,7 +2038,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with fallback certificate - no cert passed": { @@ -2154,7 +2154,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -2168,7 +2168,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with connection idle timeout set in listener config": { @@ -2224,7 +2224,7 @@ func TestListenerVisit(t *testing.T) { ConnectionIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with stream idle timeout set in listener config": { @@ -2280,7 +2280,7 @@ func TestListenerVisit(t *testing.T) { StreamIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with max connection duration set in listener config": { @@ -2336,7 +2336,7 @@ func TestListenerVisit(t *testing.T) { MaxConnectionDuration(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with delayed close timeout set in listener config": { @@ -2392,7 +2392,7 @@ func TestListenerVisit(t *testing.T) { DelayedCloseTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with connection shutdown grace period set in listener config": { @@ -2448,7 +2448,7 @@ func TestListenerVisit(t *testing.T) { ConnectionShutdownGracePeriod(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -2512,7 +2512,7 @@ func TestListenerVisit(t *testing.T) { ConnectionIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -2533,7 +2533,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with allow_chunked_length set in listener config": { @@ -2587,7 +2587,7 @@ func TestListenerVisit(t *testing.T) { AllowChunkedLength(true). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with merge_slashes set in listener config": { @@ -2642,7 +2642,7 @@ func TestListenerVisit(t *testing.T) { MergeSlashes(true). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with server_header_transformation set to pass through in listener config": { @@ -2697,7 +2697,7 @@ func TestListenerVisit(t *testing.T) { ServerHeaderTransformation(v1alpha1.PassThroughServerHeader). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with XffNumTrustedHops set in listener config": { @@ -2751,7 +2751,7 @@ func TestListenerVisit(t *testing.T) { NumTrustedHops(1). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpsproxy with secret with stream idle timeout set in listener config": { @@ -2814,7 +2814,7 @@ func TestListenerVisit(t *testing.T) { StreamIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -2835,7 +2835,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -2899,7 +2899,7 @@ func TestListenerVisit(t *testing.T) { MaxConnectionDuration(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -2920,7 +2920,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpsproxy with secret with delayed close timeout set in listener config": { @@ -2983,7 +2983,7 @@ func TestListenerVisit(t *testing.T) { DelayedCloseTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -3004,7 +3004,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpsproxy with secret with connection shutdown grace period set in listener config": { @@ -3067,7 +3067,7 @@ func TestListenerVisit(t *testing.T) { ConnectionShutdownGracePeriod(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -3088,7 +3088,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "insecure httpproxy with rate limit config": { @@ -3170,7 +3170,7 @@ func TestListenerVisit(t *testing.T) { }), }, }).Get()), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, @@ -3264,7 +3264,7 @@ func TestListenerVisit(t *testing.T) { }). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -3307,7 +3307,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "secure httpproxy using fallback certificate with rate limit config": { @@ -3416,7 +3416,7 @@ func TestListenerVisit(t *testing.T) { }). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -3496,7 +3496,56 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), + }), + }, + "DSCP marking with socket options": { + ListenerConfig: ListenerConfig{ + SocketOptions: &v1alpha1.SocketOptions{ + TOS: 64, + TrafficClass: 64, + }, + }, + objs: []any{ + &contour_api_v1.HTTPProxy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "simple", + Namespace: "default", + }, + Spec: contour_api_v1.HTTPProxySpec{ + VirtualHost: &contour_api_v1.VirtualHost{ + Fqdn: "www.example.com", + }, + Routes: []contour_api_v1.Route{{ + Conditions: []contour_api_v1.MatchCondition{{ + Prefix: "/", + }}, + Services: []contour_api_v1.Service{{ + Name: "backend", + Port: 80, + }}, + }}, + }, + }, + &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backend", + Namespace: "default", + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{{ + Name: "http", + Protocol: "TCP", + Port: 80, + }}, + }, + }, + }, + want: listenermap(&envoy_listener_v3.Listener{ + Name: ENVOY_HTTP_LISTENER, + Address: envoy_v3.SocketAddress("0.0.0.0", 8080), + FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().TOS(64).TrafficClass(64).Build(), }), }, "httpproxy with MaxRequestsPerConnection set in listener config": { @@ -3550,7 +3599,7 @@ func TestListenerVisit(t *testing.T) { MaxRequestsPerConnection(ref.To(uint32(1))). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpsproxy with MaxRequestsPerConnection set in listener config": { @@ -3611,7 +3660,7 @@ func TestListenerVisit(t *testing.T) { MaxRequestsPerConnection(ref.To(uint32(1))). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -3632,7 +3681,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpproxy with PerConnectionBufferLimitBytes set in listener config": { @@ -3686,7 +3735,7 @@ func TestListenerVisit(t *testing.T) { DefaultFilters(). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpsproxy with PerConnectionBufferLimitBytes set in listener config": { @@ -3747,7 +3796,7 @@ func TestListenerVisit(t *testing.T) { DefaultFilters(). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443), @@ -3768,7 +3817,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, } diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go index 52fb7e0dc5b..462361d226c 100644 --- a/pkg/config/parameters.go +++ b/pkg/config/parameters.go @@ -481,6 +481,9 @@ type ListenerParameters struct { // // +optional PerConnectionBufferLimitBytes *uint32 `yaml:"per-connection-buffer-limit-bytes,omitempty"` + + // SocketOptions is used to set socket options for listeners. + SocketOptions SocketOptions `yaml:"socket-options"` } func (p *ListenerParameters) Validate() error { @@ -500,6 +503,37 @@ func (p *ListenerParameters) Validate() error { return fmt.Errorf("invalid per connections buffer limit bytes value %q set on listener, minimum value is 1", *p.PerConnectionBufferLimitBytes) } + return p.SocketOptions.Validate() +} + +// SocketOptions defines configurable socket options for Envoy listeners. +type SocketOptions struct { + // Defines the value for IPv4 TOS field (including 6 bit DSCP field) for IP packets originating from Envoy listeners. + // Single value is applied to all listeners. + // The value must be in the range 0-255, 0 means socket option is not set. + // If listeners are bound to IPv6-only addresses, setting this option will cause an error. + TOS int32 `yaml:"tos"` + + // Defines the value for IPv6 Traffic Class field (including 6 bit DSCP field) for IP packets originating from the Envoy listeners. + // Single value is applied to all listeners. + // The value must be in the range 0-255, 0 means socket option is not set. + // If listeners are bound to IPv4-only addresses, setting this option will cause an error. + TrafficClass int32 `yaml:"traffic-class"` +} + +func (p *SocketOptions) Validate() error { + if p == nil { + return nil + } + + if p.TOS < 0 || p.TOS > 255 { + return fmt.Errorf("invalid listener IPv4 TOS value %d, must be in the range 0-255", p.TOS) + } + + if p.TrafficClass < 0 || p.TrafficClass > 255 { + return fmt.Errorf("invalid listener IPv6 TrafficClass value %d, must be in the range 0-255", p.TrafficClass) + } + return nil } diff --git a/pkg/config/parameters_test.go b/pkg/config/parameters_test.go index 819d819b02c..bcd46957a99 100644 --- a/pkg/config/parameters_test.go +++ b/pkg/config/parameters_test.go @@ -564,6 +564,21 @@ func TestListenerValidation(t *testing.T) { PerConnectionBufferLimitBytes: ref.To(uint32(0)), } require.Error(t, l.Validate()) + l = &ListenerParameters{ + SocketOptions: SocketOptions{ + TOS: 64, + TrafficClass: 64, + }, + } + require.NoError(t, l.Validate()) + l = &ListenerParameters{SocketOptions: SocketOptions{TOS: 256}} + require.Error(t, l.Validate()) + l = &ListenerParameters{SocketOptions: SocketOptions{TrafficClass: 256}} + require.Error(t, l.Validate()) + l = &ListenerParameters{SocketOptions: SocketOptions{TOS: -1}} + require.Error(t, l.Validate()) + l = &ListenerParameters{SocketOptions: SocketOptions{TrafficClass: -1}} + require.Error(t, l.Validate()) } func TestClusterParametersValidation(t *testing.T) { diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html index c9f2508f65b..98f35777dd2 100644 --- a/site/content/docs/main/config/api-reference.html +++ b/site/content/docs/main/config/api-reference.html @@ -6760,6 +6760,22 @@

EnvoyListenerConfig

TLS holds various configurable Envoy TLS listener values.

+ + +socketOptions +
+ + +SocketOptions + + + + +(Optional) +

SocketOptions defines configurable socket options for the listeners. +Single set of options are applied to all listeners.

+ +

EnvoyLogging @@ -8307,6 +8323,55 @@

ServerHeaderT +

SocketOptions +

+

+(Appears on: +EnvoyListenerConfig) +

+

+

SocketOptions defines configurable socket options for Envoy listeners.

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+tos +
+ +int32 + +
+(Optional) +

Defines the value for IPv4 TOS field (including 6 bit DSCP field) for IP packets originating from Envoy listeners. +Single value is applied to all listeners. +If listeners are bound to IPv6-only addresses, setting this option will cause an error.

+
+trafficClass +
+ +int32 + +
+(Optional) +

Defines the value for IPv6 Traffic Class field (including 6 bit DSCP field) for IP packets originating from the Envoy listeners. +Single value is applied to all listeners. +If listeners are bound to IPv4-only addresses, setting this option will cause an error.

+

TLS

diff --git a/site/content/docs/main/configuration.md b/site/content/docs/main/configuration.md index 98e09d2aa18..8867f89d113 100644 --- a/site/content/docs/main/configuration.md +++ b/site/content/docs/main/configuration.md @@ -194,6 +194,7 @@ The listener configuration block can be used to configure various parameters for | connection-balancer | string | `""` | This field specifies the listener connection balancer. If the value is `exact`, the listener will use the exact connection balancer to balance connections between threads in a single Envoy process. See [the Envoy documentation][14] for more information. | | max-requests-per-connection | int | none | This field specifies the maximum requests for downstream connections. If not specified, there is no limit | | per-connection-buffer-limit-bytes | int | 1MiB* | This field specifies the soft limit on size of the listener’s new connection read and write buffer. If not specified, Envoy defaults of 1MiB apply | +| socket-options | SocketOptions | | The [Socket Options](#socket-options) for Envoy listeners. | _This is Envoy's default setting value and is not explicitly configured by Contour._ @@ -282,6 +283,13 @@ Metrics and health endpoints cannot have the same port number when metrics are s | server-key-path | string | none | Optional path to the server private key file. | | ca-certificate-path | string | none | Optional path to the CA certificate file used to verify client certificates. | +### Socket Options + +| Field Name | Type | Default | Description | +| --------------- | ------ | ------- | ----------------------------------------------------------------------------- | +| tos | int | 0 | Defines the value for IPv4 TOS field (including 6 bit DSCP field) for IP packets originating from Envoy listeners. Single value is applied to all listeners. The value must be in the range 0-255, 0 means socket option is not set. If listeners are bound to IPv6-only addresses, setting this option will cause an error. | +| traffic-class | int | 0 | Defines the value for IPv6 Traffic Class field (including 6 bit DSCP field) for IP packets originating from the Envoy listeners. Single value is applied to all listeners. The value must be in the range 0-255, 0 means socket option is not set. If listeners are bound to IPv4-only addresses, setting this option will cause an error. | + ### Configuration Example The following is an example ConfigMap with configuration file included: @@ -452,6 +460,12 @@ data: # server-certificate-path: /path/to/server-cert.pem # server-key-path: /path/to/server-private-key.pem # ca-certificate-path: /path/to/root-ca-for-client-validation.pem + # + # listener: + # connection-balancer: exact + # socket-options: + # tos: 64 + # traffic-class: 64 ``` _Note:_ The default example `contour` includes this [file][1] for easy deployment of Contour. From f616af2a0067e28b51188a2866e20786ff92f9f3 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Mon, 7 Aug 2023 15:19:36 +0300 Subject: [PATCH 2/2] Added featuretest for non-default socket opts Signed-off-by: Tero Saarni --- internal/featuretests/v3/listeners_test.go | 104 +++++++++++++++++++++ internal/xdscache/v3/listener_test.go | 4 +- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/internal/featuretests/v3/listeners_test.go b/internal/featuretests/v3/listeners_test.go index c3fae12cc50..fd42dda6788 100644 --- a/internal/featuretests/v3/listeners_test.go +++ b/internal/featuretests/v3/listeners_test.go @@ -16,12 +16,14 @@ package v3 import ( "testing" + envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" contour_api_v1 "github.com/projectcontour/contour/apis/projectcontour/v1" contour_api_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1" "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3" "github.com/projectcontour/contour/internal/featuretests" "github.com/projectcontour/contour/internal/fixture" @@ -1544,3 +1546,105 @@ func TestGatewayListenersSetAddress(t *testing.T) { TypeUrl: listenerType, }) } + +func TestSocketOptions(t *testing.T) { + // Configure non-default socket options for HTTP and HTTPS listeners. + rh, c, done := setup(t, func(conf *xdscache_v3.ListenerConfig) { + conf.SocketOptions = &contour_api_v1alpha1.SocketOptions{ + TOS: 32, + TrafficClass: 64, + } + }) + defer done() + + svc1 := fixture.NewService("backend"). + WithPorts(v1.ServicePort{Name: "http", Port: 80}) + rh.OnAdd(svc1) + + // secret1 is a tls secret + secret1 := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret", + Namespace: "default", + }, + Type: "kubernetes.io/tls", + Data: featuretests.Secretdata(featuretests.CERTIFICATE, featuretests.RSA_PRIVATE_KEY), + } + rh.OnAdd(secret1) + + // p1 is a tls httpproxy + p1 := &contour_api_v1.HTTPProxy{ + ObjectMeta: fixture.ObjectMeta("simple"), + Spec: contour_api_v1.HTTPProxySpec{ + VirtualHost: &contour_api_v1.VirtualHost{ + Fqdn: "kuard.example.com", + TLS: &contour_api_v1.TLS{ + SecretName: "secret", + }, + }, + Routes: []contour_api_v1.Route{{ + Conditions: []contour_api_v1.MatchCondition{{ + Prefix: "/", + }}, + Services: []contour_api_v1.Service{{ + Name: "backend", + Port: 80, + }}, + }}, + }, + } + rh.OnAdd(p1) + + socketOpts := envoy_v3.NewSocketOptions().TCPKeepalive().Build() + + // Verify that the given socket options are set on the HTTP and HTTPS listeners. + socketOpts = append(socketOpts, &envoy_core_v3.SocketOption{ + Description: "Set IPv4 TOS field", + Level: envoy.IPPROTO_IP, + Name: envoy.IP_TOS, + State: envoy_core_v3.SocketOption_STATE_LISTENING, + Value: &envoy_core_v3.SocketOption_IntValue{IntValue: int64(32)}, + }, &envoy_core_v3.SocketOption{ + Description: "Set IPv6 Traffic Class field", + Level: envoy.IPPROTO_IPV6, + Name: envoy.IPV6_TCLASS, + State: envoy_core_v3.SocketOption_STATE_LISTENING, + Value: &envoy_core_v3.SocketOption_IntValue{IntValue: int64(64)}, + }) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + Resources: resources(t, + &envoy_listener_v3.Listener{ + Name: "ingress_http", + Address: envoy_v3.SocketAddress("0.0.0.0", 8080), + FilterChains: envoy_v3.FilterChains( + envoy_v3.HTTPConnectionManager("ingress_http", envoy_v3.FileAccessLogEnvoy("/dev/stdout", "", nil, contour_api_v1alpha1.LogLevelInfo), 0), + ), + SocketOptions: socketOpts, + }, + &envoy_listener_v3.Listener{ + Name: "ingress_https", + Address: envoy_v3.SocketAddress("0.0.0.0", 8443), + ListenerFilters: envoy_v3.ListenerFilters( + envoy_v3.TLSInspector(), + ), + FilterChains: []*envoy_listener_v3.FilterChain{ + envoy_v3.FilterChainTLS( + "kuard.example.com", + envoy_v3.DownstreamTLSContext( + &dag.Secret{Object: secret1}, + envoy_tls_v3.TlsParameters_TLSv1_2, + envoy_tls_v3.TlsParameters_TLSv1_3, + nil, + nil, + "h2", "http/1.1"), + envoy_v3.Filters(httpsFilterFor("kuard.example.com")), + ), + }, + SocketOptions: socketOpts, + }, + statsListener(), + ), + TypeUrl: listenerType, + }) +} diff --git a/internal/xdscache/v3/listener_test.go b/internal/xdscache/v3/listener_test.go index 280401a7aa2..186215e39c7 100644 --- a/internal/xdscache/v3/listener_test.go +++ b/internal/xdscache/v3/listener_test.go @@ -982,7 +982,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "tls-maximum-protocol-version from config not overridden by httpproxy": { @@ -1039,7 +1039,7 @@ func TestListenerVisit(t *testing.T) { Name: ENVOY_HTTP_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8080), FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, &envoy_listener_v3.Listener{ Name: ENVOY_HTTPS_LISTENER, Address: envoy_v3.SocketAddress("0.0.0.0", 8443),