Repository: istio/istio
File: pilot/pkg/serviceregistry/kube/controller/network.go (Go)

Code before:
			gw.Addr = addr
			newGateways.Insert(gw)
		}
	}

	gatewaysChanged := !newGateways.Equals(previousGateways)
	if len(newGateways) > 0 {
		n.networkGatewaysBySvc[svc.Hostname] = newGateways
	} else {
		delete(n.networkGatewaysBySvc, svc.Hostname)
	}

	return gatewaysChanged
}

// getGatewayDetails returns gateways without the address populated, only the network and (unmapped) port for a given service.
func (n *networkManager) getGatewayDetails(svc *model.Service) []model.NetworkGateway {
	// TODO should we start checking if svc's Ports contain the gateway port?

	// We have different types of E/W gateways - those that use mTLS (those are used in sidecar mode when talking cross networks)
	// and those that use double-HBONE (those are used in ambient mode when talking cross cluster). A gateway service may or may
	// not listen on the mTLS (15443, by default) or HBONE (15008) ports, depending on the mode of operation used by the mesh
	// in the remote cluster. We should not use gateways that don't really listen on the right port.
	hbonePort := uint32(DefaultNetworkGatewayHBONEPort)
	if _, exists := svc.Ports.GetByPort(DefaultNetworkGatewayHBONEPort); !exists {
		hbonePort = 0
	}

	// label based gateways
	// TODO label based gateways could support being the gateway for multiple networks
	if nw := svc.Attributes.Labels[label.TopologyNetwork.Name]; nw != "" {
		if gwPortStr := svc.Attributes.Labels[label.NetworkingGatewayPort.Name]; gwPortStr != "" {
			if gwPort, err := strconv.Atoi(gwPortStr); err == nil {
				return []model.NetworkGateway{{Port: uint32(gwPort), HBONEPort: hbonePort, Network: network.ID(nw)}}
			}
			log.Warnf("could not parse %q for %s on %s/%s; defaulting to %d",
				gwPortStr, label.NetworkingGatewayPort.Name, svc.Attributes.Namespace, svc.Attributes.Name, DefaultNetworkGatewayPort)
		}
		return []model.NetworkGateway{{Port: DefaultNetworkGatewayPort, HBONEPort: hbonePort, Network: network.ID(nw)}}
	}

	// meshNetworks registryServiceName+fromRegistry
	if gws, ok := n.registryServiceNameGateways[svc.Hostname]; ok {
		out := append(make([]model.NetworkGateway, 0, len(gws)), gws...)
		return out
	}

	return nil
}

// handleGateway resource adds a NetworkGateway for each combination of address and auto-passthrough listener

Review comment (suggestion):
This isn't specific to this PR, but one assumption that week make with ambient multi-network is that the e/w gateway can only be reached on port 15008. There may be reasons an e/w gateway may want to receive double hbone requests on different ports (public vs. private port or multitenancy), so we should consider documenting these assumptions in the form of TODOs (not a requirement)

Code after:
			gw.Addr = addr
			newGateways.Insert(gw)
		}
	}

	gatewaysChanged := !newGateways.Equals(previousGateways)
	if len(newGateways) > 0 {
		n.networkGatewaysBySvc[svc.Hostname] = newGateways
	} else {
		delete(n.networkGatewaysBySvc, svc.Hostname)
	}

	return gatewaysChanged
}

// getGatewayDetails returns gateways without the address populated, only the network and (unmapped) port for a given service.
func (n *networkManager) getGatewayDetails(svc *model.Service) []model.NetworkGateway {
	// We have different types of E/W gateways - those that use mTLS (those are used in sidecar mode when talking cross networks)
	// and those that use double-HBONE (those are used in ambient mode when talking cross cluster). A gateway service may or may
	// not listen on the mTLS (15443, by default) or HBONE (15008) ports, depending on the mode of operation used by the mesh
	// in the remote cluster. We should not use gateways that don't really listen on the right port.

	// label based gateways
	// TODO label based gateways could support being the gateway for multiple networks
	if nw := svc.Attributes.Labels[label.TopologyNetwork.Name]; nw != "" {
		hbonePort := DefaultNetworkGatewayHBONEPort
		gwPort := DefaultNetworkGatewayPort

		if gwPortStr := svc.Attributes.Labels[label.NetworkingGatewayPort.Name]; gwPortStr != "" {
			port, err := strconv.Atoi(gwPortStr)
			if err != nil {
				log.Warnf("could not parse %q for %s on %s/%s; defaulting to %d",
					gwPortStr, label.NetworkingGatewayPort.Name, svc.Attributes.Namespace, svc.Attributes.Name, DefaultNetworkGatewayPort)
			} else {
				gwPort = port
			}
		}

		_, acceptMTLS := svc.Ports.GetByPort(gwPort)
		_, acceptHBONE := svc.Ports.GetByPort(hbonePort)

		if !acceptMTLS && !acceptHBONE {
			log.Warnf("service %s/%s is labeled as gateway, but does not listen neither on port %d nor on port %d",
				svc.Attributes.Namespace, svc.Attributes.Name, gwPort, hbonePort)
			return nil
		}

		if !acceptMTLS {
			gwPort = 0
		}
		if !acceptHBONE {