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
}