func()

in pilot/pkg/simulation/traffic.go [281:392]


func (sim *Simulation) Run(input Call) (result Result) {
	result = Result{t: sim.t}
	input = input.FillDefaults()
	if input.Alpn != "" && input.TLS == Plaintext {
		result.Error = fmt.Errorf("invalid call, ALPN can only be sent in TLS requests")
		return result
	}

	// First we will match a listener
	l := matchListener(sim.Listeners, input)
	if l == nil {
		result.Error = ErrNoListener
		return
	}
	result.ListenerMatched = l.Name

	hasTLSInspector := hasFilterOnPort(l, xdsfilters.TLSInspector.Name, input.Port)
	if !hasTLSInspector {
		// Without tls inspector, Envoy would not read the ALPN in the TLS handshake
		// HTTP inspector still may set it though
		input.Alpn = ""
	}

	// Apply listener filters
	if hasFilterOnPort(l, xdsfilters.HTTPInspector.Name, input.Port) {
		if alpn := protocolToAlpn(input.Protocol); alpn != "" && input.TLS == Plaintext {
			input.Alpn = alpn
		}
	}

	fc, err := sim.matchFilterChain(l.FilterChains, l.DefaultFilterChain, input, hasTLSInspector)
	if err != nil {
		result.Error = err
		return
	}
	result.FilterChainMatched = fc.Name
	// Plaintext to TLS is an error
	if fc.TransportSocket != nil && input.TLS == Plaintext {
		result.Error = ErrTLSError
		return
	}

	mTLSSecretConfigName := "default"
	if input.MtlsSecretConfigName != "" {
		mTLSSecretConfigName = input.MtlsSecretConfigName
	}

	// mTLS listener will only accept mTLS traffic
	if fc.TransportSocket != nil && sim.requiresMTLS(fc, mTLSSecretConfigName) != (input.TLS == MTLS) {
		// If there is no tls inspector, then
		result.Error = ErrMTLSError
		return
	}

	if len(input.CustomListenerValidations) > 0 {
		for _, validation := range input.CustomListenerValidations {
			if err := validation(fc); err != nil {
				result.Error = err
			}
		}
	}

	if hcm := xdstest.ExtractHTTPConnectionManager(sim.t, fc); hcm != nil {
		// We matched HCM and didn't terminate TLS, but we are sending TLS traffic - decoding will fail
		if input.TLS != Plaintext && fc.TransportSocket == nil {
			result.Error = ErrProtocolError
			return
		}
		// TCP to HCM is invalid
		if input.Protocol != HTTP && input.Protocol != HTTP2 {
			result.Error = ErrProtocolError
			return
		}

		// Fetch inline route
		rc := hcm.GetRouteConfig()
		if rc == nil {
			// If not set, fallback to RDS
			routeName := hcm.GetRds().RouteConfigName
			result.RouteConfigMatched = routeName
			rc = xdstest.ExtractRouteConfigurations(sim.Routes)[routeName]
		}
		hostHeader := ""
		if len(input.Headers["Host"]) > 0 {
			hostHeader = input.Headers["Host"][0]
		}
		vh := sim.matchVirtualHost(rc, hostHeader)
		if vh == nil {
			result.Error = ErrNoVirtualHost
			return
		}
		result.VirtualHostMatched = vh.Name
		if vh.RequireTls == route.VirtualHost_ALL && input.TLS == Plaintext {
			result.Error = ErrTLSRedirect
			return
		}

		r := sim.matchRoute(vh, input)
		if r == nil {
			result.Error = ErrNoRoute
			return
		}
		result.RouteMatched = r.Name
		switch t := r.GetAction().(type) {
		case *route.Route_Route:
			result.ClusterMatched = t.Route.GetCluster()
		}
	} else if tcp := xdstest.ExtractTCPProxy(sim.t, fc); tcp != nil {
		result.ClusterMatched = tcp.GetCluster()
	}
	return
}