Repository: envoyproxy/gateway
Pull request #5027 (2025-01-09 22:54:47)

fix: dont shift listener ports for Standalone mode
Fixes: https://github.com/envoyproxy/gateway/issues/4981

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/5027?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
Attention: Patch coverage is `59.09091%` with `9 lines` in your changes missing coverage. Please review.
> Project coverage is 66.79%. Comparing base [(`6466ceb`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/6466ceb1b80d827c78b5f03c8bcd34f012260bce?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`08825b2`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/08825b200c57ff3540013da9a3a1bbf5cd4f74e9?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).
> Report is 3 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/envoyproxy/gateway/pull/5027?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) | Patch % | Lines |
|---|---|---|
| [internal/gatewayapi/runner/runner.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/5027?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Frunner%2Frunner.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9ydW5uZXIvcnVubmVyLmdv) | 0.00% | [9 Missing :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/5027?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #5027      +/-   ##
==========================================
+ Coverage   66.76%   66.79%   +0.03%     
==========================================
  Files         209      209              
  Lines       32255    32362     +107     
==========================================
+ Hits        21534    21617      +83     
- Misses       9427     9442      +15     
- Partials     1294     1303       +9     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/5027?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).


Patch:
diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go
index ad505562d..416ce9808 100644
--- a/internal/gatewayapi/helpers.go
+++ b/internal/gatewayapi/helpers.go
@@ -249,25 +249,6 @@ func OwnerLabels(gateway *gwapiv1.Gateway, mergeGateways bool) map[string]string
 	return GatewayOwnerLabels(gateway.Namespace, gateway.Name)
 }
 
-// servicePortToContainerPort translates a service port into an ephemeral
-// container port.
-func servicePortToContainerPort(servicePort int32, envoyProxy *egv1a1.EnvoyProxy) int32 {
-	if envoyProxy != nil {
-		if !envoyProxy.NeedToSwitchPorts() {
-			return servicePort
-		}
-	}
-
-	// If the service port is a privileged port (1-1023)
-	// add a constant to the value converting it into an ephemeral port.
-	// This allows the container to bind to the port without needing a
-	// CAP_NET_BIND_SERVICE capability.
-	if servicePort < minEphemeralPort {
-		return servicePort + wellKnownPortShift
-	}
-	return servicePort
-}
-
 // computeHosts returns a list of intersecting listener hostnames and route hostnames
 // that don't intersect with other listener hostnames.
 func computeHosts(routeHostnames []string, listenerContext *ListenerContext) []string {
diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go
index 18fbebb0a..950290c28 100644
--- a/internal/gatewayapi/listener.go
+++ b/internal/gatewayapi/listener.go
@@ -109,7 +109,7 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource
 
 			// Add the listener to the Xds IR
 			servicePort := &protocolPort{protocol: listener.Protocol, port: int32(listener.Port)}
-			containerPort := servicePortToContainerPort(int32(listener.Port), gateway.envoyProxy)
+			containerPort := t.servicePortToContainerPort(int32(listener.Port), gateway.envoyProxy)
 			switch listener.Protocol {
 			case gwapiv1.HTTPProtocolType, gwapiv1.HTTPSProtocolType:
 				irListener := &ir.HTTPListener{
@@ -552,3 +552,27 @@ func validCELExpression(expr string) bool {
 	_, issue := celEnv.Parse(expr)
 	return issue.Err() == nil
 }
+
+// servicePortToContainerPort translates a service port into an ephemeral
+// container port.
+func (t *Translator) servicePortToContainerPort(servicePort int32, envoyProxy *egv1a1.EnvoyProxy) int32 {
+	if t.ListenerPortShiftDisabled {
+		return servicePort
+	}
+
+	if envoyProxy != nil {
+		if !envoyProxy.NeedToSwitchPorts() {
+			return servicePort
+		}
+	}
+
+	// If the service port is a privileged port (1-1023)
+	// add a constant to the value converting it into an ephemeral port.
+	// This allows the container to bind to the port without needing a
+	// CAP_NET_BIND_SERVICE capability.
+	if servicePort < minEphemeralPort {
+		return servicePort + wellKnownPortShift
+	}
+
+	return servicePort
+}
diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go
index 629758929..9c2bf9c5d 100644
--- a/internal/gatewayapi/runner/runner.go
+++ b/internal/gatewayapi/runner/runner.go
@@ -144,14 +144,15 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) {
 			for _, resources := range *val {
 				// Translate and publish IRs.
 				t := &gatewayapi.Translator{
-					GatewayControllerName:   r.Server.EnvoyGateway.Gateway.ControllerName,
-					GatewayClassName:        gwapiv1.ObjectName(resources.GatewayClass.Name),
-					GlobalRateLimitEnabled:  r.EnvoyGateway.RateLimit != nil,
-					EnvoyPatchPolicyEnabled: r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy,
-					BackendEnabled:          r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableBackend,
-					Namespace:               r.Namespace,
-					MergeGateways:           gatewayapi.IsMergeGatewaysEnabled(resources),
-					WasmCache:               r.wasmCache,
+					GatewayControllerName:     r.Server.EnvoyGateway.Gateway.ControllerName,
+					GatewayClassName:          gwapiv1.ObjectName(resources.GatewayClass.Name),
+					GlobalRateLimitEnabled:    r.EnvoyGateway.RateLimit != nil,
+					EnvoyPatchPolicyEnabled:   r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy,
+					BackendEnabled:            r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableBackend,
+					Namespace:                 r.Namespace,
+					MergeGateways:             gatewayapi.IsMergeGatewaysEnabled(resources),
+					WasmCache:                 r.wasmCache,
+					ListenerPortShiftDisabled: r.EnvoyGateway.Provider != nil && r.EnvoyGateway.Provider.IsRunningOnHost(),
 				}
 
 				// If an extension is loaded, pass its supported groups/kinds to the translator
diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go
index 23e651b6c..27963570d 100644
--- a/internal/gatewayapi/translator.go
+++ b/internal/gatewayapi/translator.go
@@ -91,6 +91,11 @@ type Translator struct {
 
 	// WasmCache is the cache for Wasm modules.
 	WasmCache wasm.Cache
+
+	// ListenerPortShiftDisabled disables translating the
+	// gateway listener port into a non privileged port
+	// and reuses the specified value.
+	ListenerPortShiftDisabled bool
 }
 
 type TranslateResult struct {


Test patch:
diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go
index 96a88bfde..6ac3765f0 100644
--- a/internal/gatewayapi/translator_test.go
+++ b/internal/gatewayapi/translator_test.go
@@ -763,9 +763,10 @@ func TestIsValidCrossNamespaceRef(t *testing.T) {
 
 func TestServicePortToContainerPort(t *testing.T) {
 	testCases := []struct {
-		servicePort   int32
-		containerPort int32
-		envoyProxy    *egv1a1.EnvoyProxy
+		servicePort               int32
+		containerPort             int32
+		envoyProxy                *egv1a1.EnvoyProxy
+		listenerPortShiftDisabled bool
 	}{
 		{
 			servicePort:   99,
@@ -826,10 +827,15 @@ func TestServicePortToContainerPort(t *testing.T) {
 				},
 			},
 		},
+		{
+			servicePort:               99,
+			containerPort:             99,
+			listenerPortShiftDisabled: true,
+		},
 	}
-
 	for _, tc := range testCases {
-		got := servicePortToContainerPort(tc.servicePort, tc.envoyProxy)
+		translator := &Translator{ListenerPortShiftDisabled: tc.listenerPortShiftDisabled}
+		got := translator.servicePortToContainerPort(tc.servicePort, tc.envoyProxy)
 		assert.Equal(t, tc.containerPort, got)
 	}
 }