Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions cmd/atenet/internal/router/xds.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,13 @@ const actorConnectCircuitBreakerLimit = 1048576
// tunnelIdleTimeout closes unused tunnels, which hold actor connections.
const tunnelIdleTimeout = 60 * time.Second

// HTTP/2 limits on the client-facing HCMs. Envoy's defaults allow 2^31-1
// streams and 256 MiB windows per connection. These match atenet-egress.
const (
downstreamMaxConcurrentStreams = 100
downstreamInitialWindowSize = 1 << 20
)

// XdsServer implements an aggregated discovery service server for dynamic Envoy router nodes.
type XdsServer struct {
xdsPort int
Expand Down Expand Up @@ -1316,14 +1323,22 @@ func (x *XdsServer) buildConnectTerminateHCM(statPrefix string) *anypb.Any {
},
},
},
Http2ProtocolOptions: &corev3.Http2ProtocolOptions{
AllowConnect: true,
},
Http2ProtocolOptions: downstreamHttp2Options(true),
})

return hcm
}

// downstreamHttp2Options returns the HTTP/2 limits for a client-facing HCM.
func downstreamHttp2Options(allowConnect bool) *corev3.Http2ProtocolOptions {
return &corev3.Http2ProtocolOptions{
AllowConnect: allowConnect,
MaxConcurrentStreams: wrapperspb.UInt32(downstreamMaxConcurrentStreams),
InitialStreamWindowSize: wrapperspb.UInt32(downstreamInitialWindowSize),
InitialConnectionWindowSize: wrapperspb.UInt32(downstreamInitialWindowSize),
}
}

func buildConnectRoutes() *routev3.RouteConfiguration {
return &routev3.RouteConfiguration{
Name: "default",
Expand Down Expand Up @@ -1435,9 +1450,10 @@ func (x *XdsServer) buildHcm(statPrefix string, captureActorRouting bool) *anypb
UpgradeConfigs: []*hcmv3.HttpConnectionManager_UpgradeConfig{
{UpgradeType: "websocket"},
},
Tracing: x.buildTracing(),
AccessLog: stdoutAccessLog(accessLogFormat),
HttpFilters: httpFilters,
Tracing: x.buildTracing(),
AccessLog: stdoutAccessLog(accessLogFormat),
HttpFilters: httpFilters,
Http2ProtocolOptions: downstreamHttp2Options(false),
RouteSpecifier: &hcmv3.HttpConnectionManager_Rds{
Rds: &hcmv3.Rds{
RouteConfigName: RouteName,
Expand Down
42 changes: 42 additions & 0 deletions cmd/atenet/internal/router/xds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,48 @@ func TestXdsServer_AccessLogsOmitQueryString(t *testing.T) {
}
}

// Every HCM serves client-controlled requests, either directly or from inside
// a client's CONNECT tunnel.
func TestXdsServer_ClientFacingHCMLimits(t *testing.T) {
server := NewXdsServer(18000)
server.SetConfig(50053, "127.0.0.1")
server.SetConnectTLSPort(8444)
setIngressTLS(server)

var got []string
for name, l := range snapshotListeners(t, server) {
for _, fc := range l.GetFilterChains() {
for _, f := range fc.GetFilters() {
if f.GetName() != "envoy.filters.network.http_connection_manager" {
continue
}
got = append(got, name)
hcm := &hcmv3.HttpConnectionManager{}
if err := f.GetTypedConfig().UnmarshalTo(hcm); err != nil {
t.Fatalf("listener %s: unmarshal HCM: %v", name, err)
}
h2 := hcm.GetHttp2ProtocolOptions()
if want := name == "connect_terminate_tls"; h2.GetAllowConnect() != want {
t.Errorf("listener %s: allow_connect = %v, want %v", name, h2.GetAllowConnect(), want)
}
if v := h2.GetMaxConcurrentStreams().GetValue(); v != downstreamMaxConcurrentStreams {
t.Errorf("listener %s: max_concurrent_streams = %d, want %d", name, v, downstreamMaxConcurrentStreams)
}
if v := h2.GetInitialStreamWindowSize().GetValue(); v != downstreamInitialWindowSize {
t.Errorf("listener %s: initial_stream_window_size = %d, want %d", name, v, downstreamInitialWindowSize)
}
if v := h2.GetInitialConnectionWindowSize().GetValue(); v != downstreamInitialWindowSize {
t.Errorf("listener %s: initial_connection_window_size = %d, want %d", name, v, downstreamInitialWindowSize)
}
}
}
}
slices.Sort(got)
if want := []string{"connect_terminate_tls", IngressHTTPSListener, MainInternalName}; !slices.Equal(got, slices.Sorted(slices.Values(want))) {
t.Errorf("HCM listeners = %v, want %v", got, want)
}
}

func TestXdsServer_Serve_Shutdown(t *testing.T) {
server := NewXdsServer(18000)
server.SetConfig(50053, "127.0.0.1")
Expand Down
Loading