diff --git a/apis/projectcontour/v1alpha1/contourconfig.go b/apis/projectcontour/v1alpha1/contourconfig.go index 0375642b75a..10b916724b3 100644 --- a/apis/projectcontour/v1alpha1/contourconfig.go +++ b/apis/projectcontour/v1alpha1/contourconfig.go @@ -369,6 +369,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 63ad9b433a0..07eb20a8fe1 100644 --- a/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go +++ b/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go @@ -551,6 +551,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. @@ -1095,6 +1100,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/cmd/contour/serve.go b/cmd/contour/serve.go index 95432e0a408..6677c48b8e4 100644 --- a/cmd/contour/serve.go +++ b/cmd/contour/serve.go @@ -392,6 +392,7 @@ func (s *Server) doServe() error { ServerHeaderTransformation: contourConfiguration.Envoy.Listener.ServerHeaderTransformation, XffNumTrustedHops: *contourConfiguration.Envoy.Network.XffNumTrustedHops, ConnectionBalancer: contourConfiguration.Envoy.Listener.ConnectionBalancer, + 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 d4a72a74fbb..f0c60475a2b 100644 --- a/cmd/contour/servecontext.go +++ b/cmd/contour/servecontext.go @@ -513,6 +513,10 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_api_v1alpha MinimumProtocolVersion: ctx.Config.TLS.MinimumProtocolVersion, 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 eb6ca68c97d..b9a672d8ad0 100644 --- a/cmd/contour/servecontext_test.go +++ b/cmd/contour/servecontext_test.go @@ -412,6 +412,10 @@ func TestConvertServeContext(t *testing.T) { TLS: &contour_api_v1alpha1.EnvoyTLS{ MinimumProtocolVersion: "", }, + 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 1e76311a976..361a0d4f135 100644 --- a/examples/contour/01-crds.yaml +++ b/examples/contour/01-crds.yaml @@ -192,6 +192,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. @@ -3353,6 +3379,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 54c3e47cfad..a47b847f717 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 @@ -405,6 +411,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. @@ -3566,6 +3598,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 1068485fdd0..22c795e7991 100644 --- a/examples/render/contour-gateway-provisioner.yaml +++ b/examples/render/contour-gateway-provisioner.yaml @@ -206,6 +206,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. @@ -3367,6 +3393,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 1ec4d2d45cc..2095406369e 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 @@ -411,6 +417,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. @@ -3572,6 +3604,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 00c9850fe1e..35d368427d3 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 @@ -405,6 +411,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. @@ -3566,6 +3598,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 9012e8a8c41..14a5fb1793c 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, lf []*envoy_listener_v3.ListenerFilter, filters ...*envoy_listener_v3.Filter) *envoy_listener_v3.Listener { +func Listener(name, address string, port int, 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 len(filters) > 0 { l.FilterChains = append( diff --git a/internal/envoy/v3/listener_test.go b/internal/envoy/v3/listener_test.go index a38d70b9d5c..e0427196a68 100644 --- a/internal/envoy/v3/listener_test.go +++ b/internal/envoy/v3/listener_test.go @@ -98,7 +98,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": { @@ -120,7 +120,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": { @@ -136,7 +136,7 @@ func TestListener(t *testing.T) { ListenerFilters: ListenerFilters( TLSInspector(), ), - SocketOptions: TCPKeepaliveSocketOptions(), + SocketOptions: NewSocketOptions().TCPKeepalive().Build(), }, }, "secure listener w/ proxy": { @@ -154,14 +154,14 @@ func TestListener(t *testing.T) { ProxyProtocol(), 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.lf, tc.f...) + got := Listener(tc.name, tc.address, tc.port, 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 031fe6635c8..7156d5b5d9f 100644 --- a/internal/featuretests/v3/authorization_test.go +++ b/internal/featuretests/v3/authorization_test.go @@ -107,7 +107,7 @@ func authzResponseTimeout(t *testing.T, rh cache.ResourceEventHandler, c *Contou ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener()), @@ -194,7 +194,7 @@ func authzFailOpen(t *testing.T, rh cache.ResourceEventHandler, c *Contour) { ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener()), }).Status(p).IsValid() @@ -509,7 +509,7 @@ func authzInvalidReference(t *testing.T, rh cache.ResourceEventHandler, c *Conto ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener()), }).Status(invalid).IsValid() @@ -578,7 +578,7 @@ func authzWithRequestBodyBufferSettings(t *testing.T, rh cache.ResourceEventHand ), 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 b4f42a21763..4a654cfc654 100644 --- a/internal/featuretests/v3/envoy.go +++ b/internal/featuretests/v3/envoy.go @@ -567,6 +567,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 6663deb2ae5..2313a0a83e6 100644 --- a/internal/featuretests/v3/global_authorization_test.go +++ b/internal/featuretests/v3/global_authorization_test.go @@ -136,7 +136,7 @@ func globalExternalAuthorizationFilterExistsTLS(t *testing.T, rh cache.ResourceE ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -199,7 +199,7 @@ func globalExternalAuthorizationWithTLSGlobalAuthDisabled(t *testing.T, rh cache 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{ @@ -348,7 +348,7 @@ func globalExternalAuthorizationWithMergedAuthPolicyTLS(t *testing.T, rh cache.R ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), } c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ @@ -475,7 +475,7 @@ func globalExternalAuthorizationWithTLSAuthOverride(t *testing.T, rh cache.Resou ), 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 8a0c80ce6f6..18103784284 100644 --- a/internal/featuretests/v3/httproute_test.go +++ b/internal/featuretests/v3/httproute_test.go @@ -183,7 +183,7 @@ func TestGateway_TLS(t *testing.T) { httpsFilterFor("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 f396695aa2c..e4d9215cf43 100644 --- a/internal/featuretests/v3/jwtverification_test.go +++ b/internal/featuretests/v3/jwtverification_test.go @@ -92,7 +92,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(), }, ), }) @@ -170,7 +170,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{ @@ -323,7 +323,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{ @@ -431,7 +431,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{ @@ -561,7 +561,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{ @@ -655,7 +655,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{ @@ -809,7 +809,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{ @@ -973,7 +973,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{ @@ -1119,7 +1119,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{ @@ -1252,7 +1252,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(), }, ), }) @@ -1340,7 +1340,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{ @@ -1503,7 +1503,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{ @@ -1621,7 +1621,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{ @@ -1761,7 +1761,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 dcd4b3fc461..8000f430def 100644 --- a/internal/featuretests/v3/listeners_test.go +++ b/internal/featuretests/v3/listeners_test.go @@ -208,7 +208,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(), ), @@ -253,7 +253,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(), ), @@ -361,7 +361,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 @@ -410,7 +410,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 @@ -491,7 +491,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 @@ -570,7 +570,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, @@ -728,7 +728,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, @@ -824,7 +824,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, @@ -918,7 +918,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", @@ -1004,7 +1004,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", @@ -1081,7 +1081,7 @@ func TestHTTPProxyMinimumTLSVersion(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 @@ -1137,7 +1137,7 @@ func TestHTTPProxyMinimumTLSVersion(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 diff --git a/internal/featuretests/v3/routeweight_test.go b/internal/featuretests/v3/routeweight_test.go index 43eded31fc7..0059afd0761 100644 --- a/internal/featuretests/v3/routeweight_test.go +++ b/internal/featuretests/v3/routeweight_test.go @@ -144,7 +144,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(), ), @@ -200,7 +200,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(), ), @@ -256,7 +256,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(), ), @@ -313,7 +313,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(), ), @@ -528,7 +528,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(), ), @@ -587,7 +587,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/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 bbc328f6efc..0e854d81b2f 100644 --- a/internal/featuretests/v3/tlsprotocolversion_test.go +++ b/internal/featuretests/v3/tlsprotocolversion_test.go @@ -81,7 +81,7 @@ func TestTLSMinimumProtocolVersion(t *testing.T) { httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, ), TypeUrl: listenerType, @@ -128,7 +128,7 @@ func TestTLSMinimumProtocolVersion(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 04bb31eff08..9797b3a36c1 100644 --- a/internal/featuretests/v3/tlsroute_test.go +++ b/internal/featuretests/v3/tlsroute_test.go @@ -112,7 +112,7 @@ func TestTLSRoute(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -160,7 +160,7 @@ func TestTLSRoute(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }, statsListener(), ), @@ -232,7 +232,7 @@ func TestTLSRoute(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/wildcardhost_test.go b/internal/featuretests/v3/wildcardhost_test.go index 92fc5ee3d27..3a5588fbd07 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 cc986830120..90900cddd3c 100644 --- a/internal/xdscache/v3/listener.go +++ b/internal/xdscache/v3/listener.go @@ -132,6 +132,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 TracingConfig struct { @@ -347,6 +350,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 { // If there are non-TLS vhosts bound to the listener, // add a listener with a single filter chain. @@ -376,6 +384,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { listener.Name, listener.Address, listener.Port, + socketOptions, proxyProtocol(cfg.UseProxyProto), cm, ) @@ -389,6 +398,7 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { listener.Name, listener.Address, listener.Port, + socketOptions, secureProxyProtocol(cfg.UseProxyProto), ) } diff --git a/internal/xdscache/v3/listener_test.go b/internal/xdscache/v3/listener_test.go index ded08b22a41..254535c4b32 100644 --- a/internal/xdscache/v3/listener_test.go +++ b/internal/xdscache/v3/listener_test.go @@ -55,14 +55,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(), }, }, }, @@ -89,7 +89,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{ @@ -97,7 +97,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(), }, }, }, @@ -106,7 +106,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{ @@ -114,7 +114,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(), }, }, }, @@ -123,7 +123,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, @@ -197,7 +197,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": { @@ -240,7 +240,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 ingress with secret": { @@ -293,7 +293,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), @@ -307,7 +307,7 @@ func TestListenerVisit(t *testing.T) { TransportSocket: transportSocket("secret", envoy_tls_v3.TlsParameters_TLSv1_2, nil, "h2", "http/1.1"), Filters: envoy_v3.Filters(httpsFilterFor("whatever.example.com")), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "multiple tls ingress with secrets should be sorted": { @@ -382,7 +382,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), @@ -402,7 +402,7 @@ func TestListenerVisit(t *testing.T) { TransportSocket: transportSocket("secret", envoy_tls_v3.TlsParameters_TLSv1_2, nil, "h2", "http/1.1"), Filters: envoy_v3.Filters(httpsFilterFor("sortedsecond.example.com")), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "simple ingress with missing secret": { @@ -455,7 +455,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": { @@ -506,7 +506,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), @@ -520,7 +520,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "ingress with allow-http: false": { @@ -602,7 +602,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": { @@ -661,7 +661,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), @@ -676,7 +676,7 @@ func TestListenerVisit(t *testing.T) { TransportSocket: transportSocket("secret", envoy_tls_v3.TlsParameters_TLSv1_2, nil, "h2", "http/1.1"), Filters: envoy_v3.Filters(httpsFilterFor("whatever.example.com")), }}, - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "--envoy-http-access-log": { @@ -733,7 +733,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), @@ -753,7 +753,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(), }), }, "tls-min-protocol-version from config": { @@ -809,7 +809,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), @@ -823,7 +823,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "tls-min-protocol-version from config overridden by annotation": { @@ -882,7 +882,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), @@ -896,7 +896,7 @@ func TestListenerVisit(t *testing.T) { ListenerFilters: envoy_v3.ListenerFilters( envoy_v3.TLSInspector(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "tls-min-protocol-version from config overridden by httpproxy": { @@ -951,7 +951,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), @@ -965,7 +965,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": { @@ -1022,7 +1022,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), @@ -1036,7 +1036,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 and with request timeout set": { @@ -1116,7 +1116,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), @@ -1152,7 +1152,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 and with connection idle timeout set": { @@ -1232,7 +1232,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), @@ -1268,7 +1268,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 and with stream idle timeout set": { @@ -1348,7 +1348,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), @@ -1384,7 +1384,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 and with delayed close timeout set": { @@ -1464,7 +1464,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), @@ -1500,7 +1500,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 and with max connection duration set": { @@ -1580,7 +1580,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), @@ -1616,7 +1616,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 and with connection shutdown grace period set": { @@ -1696,7 +1696,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), @@ -1732,7 +1732,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": { @@ -1800,7 +1800,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), @@ -1821,7 +1821,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": { @@ -1914,7 +1914,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), @@ -1944,7 +1944,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": { @@ -2059,7 +2059,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), @@ -2073,7 +2073,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": { @@ -2129,7 +2129,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": { @@ -2185,7 +2185,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": { @@ -2241,7 +2241,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": { @@ -2297,7 +2297,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": { @@ -2353,7 +2353,7 @@ func TestListenerVisit(t *testing.T) { ConnectionShutdownGracePeriod(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "httpsproxy with secret with connection idle timeout set in listener config": { @@ -2416,7 +2416,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), @@ -2437,7 +2437,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": { @@ -2491,7 +2491,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": { @@ -2546,7 +2546,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": { @@ -2601,7 +2601,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": { @@ -2655,7 +2655,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": { @@ -2718,7 +2718,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), @@ -2739,7 +2739,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 max connection duration set in listener config": { @@ -2802,7 +2802,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), @@ -2823,7 +2823,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": { @@ -2886,7 +2886,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), @@ -2907,7 +2907,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": { @@ -2970,7 +2970,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), @@ -2991,7 +2991,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": { @@ -3071,7 +3071,7 @@ func TestListenerVisit(t *testing.T) { }), }, }).Get()), - SocketOptions: envoy_v3.TCPKeepaliveSocketOptions(), + SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), }), }, "secure httpproxy with rate limit config": { @@ -3162,7 +3162,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), @@ -3205,7 +3205,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": { @@ -3312,7 +3312,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), @@ -3392,7 +3392,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: []interface{}{ + &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(), }), }, } diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go index 78ed5d4aaf8..678af2e7bfc 100644 --- a/pkg/config/parameters.go +++ b/pkg/config/parameters.go @@ -436,6 +436,9 @@ type ListenerParameters struct { // See https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/listener.proto#envoy-api-msg-listener-connectionbalanceconfig // for more information. ConnectionBalancer string `yaml:"connection-balancer"` + + // SocketOptions is used to set socket options for listeners. + SocketOptions SocketOptions `yaml:"socket-options"` } func (p *ListenerParameters) Validate() error { @@ -446,6 +449,38 @@ func (p *ListenerParameters) Validate() error { if p.ConnectionBalancer != "" && p.ConnectionBalancer != "exact" { return fmt.Errorf("invalid listener connection balancer value %q, only 'exact' connection balancing is supported for now", p.ConnectionBalancer) } + + 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 ba262651963..cd1e3627b5c 100644 --- a/pkg/config/parameters_test.go +++ b/pkg/config/parameters_test.go @@ -492,6 +492,21 @@ func TestListenerValidation(t *testing.T) { ConnectionBalancer: "invalid", } 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 TestTracingConfigValidation(t *testing.T) { diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html index 44f3c2c4e5d..09b07b5bd2d 100644 --- a/site/content/docs/main/config/api-reference.html +++ b/site/content/docs/main/config/api-reference.html @@ -6515,6 +6515,22 @@
TLS holds various configurable Envoy TLS listener values.
+socketOptions
+SocketOptions defines configurable socket options for the listeners. +Single set of options are applied to all listeners.
++(Appears on: +EnvoyListenerConfig) +
++
SocketOptions defines configurable socket options for Envoy listeners.
+ +Field | +Description | +
---|---|
+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. + |
+
diff --git a/site/content/docs/main/configuration.md b/site/content/docs/main/configuration.md
index 273d4a248fb..01259f7ea02 100644
--- a/site/content/docs/main/configuration.md
+++ b/site/content/docs/main/configuration.md
@@ -79,7 +79,7 @@ Where Contour settings can also be specified with command-line flags, the comman
| debug | boolean | `false` | Enables debug logging. |
| default-http-versions | string array | HTTP/1.1
HTTP/2
| This array specifies the HTTP versions that Contour should program Envoy to serve. HTTP versions are specified as strings of the form "HTTP/x", where "x" represents the version number. |
| disableAllowChunkedLength | boolean | `false` | If this field is true, Contour will disable the RFC-compliant Envoy behavior to strip the `Content-Length` header if `Transfer-Encoding: chunked` is also set. This is an emergency off-switch to revert back to Envoy's default behavior in case of failures.
-| disableMergeSlashes | boolean | `false` | This field disables Envoy's non-standard merge_slashes path transformation behavior that strips duplicate slashes from request URL paths.
+| disableMergeSlashes | boolean | `false` | This field disables Envoy's non-standard merge_slashes path transformation behavior that strips duplicate slashes from request URL paths.
| serverHeaderTransformation | string | `overwrite` | This field defines the action to be applied to the Server header on the response path. Values: `overwrite` (default), `append_if_absent`, `pass_through`
| disablePermitInsecure | boolean | `false` | If this field is true, Contour will ignore `PermitInsecure` field in HTTPProxy documents. |
| envoy-service-name | string | `envoy` | This sets the service name that will be inspected for address details to be applied to Ingress objects. |
@@ -186,6 +186,7 @@ The listener configuration block can be used to configure various parameters for
| Field Name | Type | Default | Description |
| ------------------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 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. |
+| socket-options | SocketOptions | | The [Socket Options](#socket-options) for Envoy listeners. |
### Server Configuration
@@ -272,6 +273,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:
@@ -436,6 +444,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.