diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index da082d887..35fc9da17 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -130,7 +130,6 @@ func maybeFailTimerHandler(e *endpoint, f func() tcpip.Error) func() { e.lastError = err e.lastErrorMu.Unlock() e.hardError = err - e.stack.Stats().TCP.CurrentConnected.Decrement() e.cleanupLocked() e.setEndpointState(StateError) e.mu.Unlock() @@ -1050,7 +1049,6 @@ func (e *endpoint) transitionToStateCloseLocked() { } if s.connected() { - e.stack.Stats().TCP.CurrentConnected.Decrement() e.stack.Stats().TCP.EstablishedClosed.Increment() } diff --git a/pkg/tcpip/transport/tcp/dispatcher.go b/pkg/tcpip/transport/tcp/dispatcher.go index d4d5c197c..8b604cbf1 100644 --- a/pkg/tcpip/transport/tcp/dispatcher.go +++ b/pkg/tcpip/transport/tcp/dispatcher.go @@ -196,7 +196,6 @@ func (p *processor) handleConnected(ep *endpoint) { fallthrough case ep.EndpointState() == StateClose: ep.mu.Unlock() - ep.stack.Stats().TCP.CurrentConnected.Decrement() ep.drainClosingSegmentQueue() ep.waiterQueue.Notify(waiter.EventHUp | waiter.EventErr | waiter.ReadableEvents | waiter.WritableEvents) return diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index e960d6ef8..e0ffc7b95 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -731,6 +731,9 @@ func (e *endpoint) setEndpointState(state EndpointState) { if oldstate == StateCloseWait || oldstate == StateEstablished { e.stack.Stats().TCP.EstablishedResets.Increment() } + if oldstate.connected() { + e.stack.Stats().TCP.CurrentConnected.Decrement() + } fallthrough default: if oldstate == StateEstablished { @@ -977,7 +980,6 @@ func (e *endpoint) Abort() { // Reset all connected endpoints. switch state := e.EndpointState(); { case state.connected(): - e.stack.Stats().TCP.CurrentConnected.Decrement() e.resetConnectionLocked(&tcpip.ErrAborted{}) return } diff --git a/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go b/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go index 1d0786a69..6776a05a2 100644 --- a/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go @@ -292,6 +292,37 @@ func TestCloseWithoutConnect(t *testing.T) { } } +func TestHandshakeTimeoutConnectedCount(t *testing.T) { + c := context.New(t, e2e.DefaultMTU) + defer c.Cleanup() + + ep, err := c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ) + if err != nil { + t.Fatalf("NewEndpoint failed: %s", err) + } + c.EP = ep + + we, ch := waiter.NewChannelEntry(waiter.WritableEvents) + c.WQ.EventRegister(&we) + defer c.WQ.EventUnregister(&we) + + switch err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestAddr, Port: context.TestPort}).(type) { + case *tcpip.ErrConnectStarted: + default: + t.Fatalf("Connect did not start: %v", err) + } + + <-ch + switch err := c.EP.LastError().(type) { + case *tcpip.ErrTimeout: + default: + t.Fatalf("Connect didn't timeout: %v", err) + } + if got, want := c.Stack().Stats().TCP.CurrentConnected.Value(), uint64(0); got != want { + t.Fatalf("got stats.TCP.CurrentConnected.Value() = %d, want = %d", got, want) + } +} + func TestTCPSegmentsSentIncrement(t *testing.T) { c := context.New(t, e2e.DefaultMTU) defer c.Cleanup()