mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add a new TCP stat for current open connections.
Such a stat accounts for all connections that are currently established and not yet transitioned to close state. Also fix bug in double increment of CurrentEstablished stat. Fixes #1579 PiperOrigin-RevId: 290827365
This commit is contained in:
@@ -150,7 +150,8 @@ var Metrics = tcpip.Stats{
|
||||
TCP: tcpip.TCPStats{
|
||||
ActiveConnectionOpenings: mustCreateMetric("/netstack/tcp/active_connection_openings", "Number of connections opened successfully via Connect."),
|
||||
PassiveConnectionOpenings: mustCreateMetric("/netstack/tcp/passive_connection_openings", "Number of connections opened successfully via Listen."),
|
||||
CurrentEstablished: mustCreateMetric("/netstack/tcp/current_established", "Number of connections in either ESTABLISHED or CLOSE-WAIT state now."),
|
||||
CurrentEstablished: mustCreateMetric("/netstack/tcp/current_established", "Number of connections in ESTABLISHED state now."),
|
||||
CurrentConnected: mustCreateMetric("/netstack/tcp/current_open", "Number of connections that are in connected state."),
|
||||
EstablishedResets: mustCreateMetric("/netstack/tcp/established_resets", "Number of times TCP connections have made a direct transition to the CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state"),
|
||||
EstablishedClosed: mustCreateMetric("/netstack/tcp/established_closed", "number of times established TCP connections made a transition to CLOSED state."),
|
||||
EstablishedTimedout: mustCreateMetric("/netstack/tcp/established_timedout", "Number of times an established connection was reset because of keep-alive time out."),
|
||||
|
||||
+5
-1
@@ -938,9 +938,13 @@ type TCPStats struct {
|
||||
PassiveConnectionOpenings *StatCounter
|
||||
|
||||
// CurrentEstablished is the number of TCP connections for which the
|
||||
// current state is either ESTABLISHED or CLOSE-WAIT.
|
||||
// current state is ESTABLISHED.
|
||||
CurrentEstablished *StatCounter
|
||||
|
||||
// CurrentConnected is the number of TCP connections that
|
||||
// are in connected state.
|
||||
CurrentConnected *StatCounter
|
||||
|
||||
// EstablishedResets is the number of times TCP connections have made
|
||||
// a direct transition to the CLOSED state from either the
|
||||
// ESTABLISHED state or the CLOSE-WAIT state.
|
||||
|
||||
@@ -562,7 +562,6 @@ func (e *endpoint) handleListenSegment(ctx *listenContext, s *segment) {
|
||||
// Switch state to connected.
|
||||
// We do not use transitionToStateEstablishedLocked here as there is
|
||||
// no handshake state available when doing a SYN cookie based accept.
|
||||
n.stack.Stats().TCP.CurrentEstablished.Increment()
|
||||
n.isConnectNotified = true
|
||||
n.setEndpointState(StateEstablished)
|
||||
|
||||
|
||||
@@ -934,6 +934,7 @@ func (e *endpoint) transitionToStateCloseLocked() {
|
||||
// Mark the endpoint as fully closed for reads/writes.
|
||||
e.cleanupLocked()
|
||||
e.setEndpointState(StateClose)
|
||||
e.stack.Stats().TCP.CurrentConnected.Decrement()
|
||||
e.stack.Stats().TCP.EstablishedClosed.Increment()
|
||||
}
|
||||
|
||||
|
||||
@@ -594,6 +594,7 @@ func (e *endpoint) setEndpointState(state EndpointState) {
|
||||
switch state {
|
||||
case StateEstablished:
|
||||
e.stack.Stats().TCP.CurrentEstablished.Increment()
|
||||
e.stack.Stats().TCP.CurrentConnected.Increment()
|
||||
case StateError:
|
||||
fallthrough
|
||||
case StateClose:
|
||||
|
||||
@@ -470,6 +470,89 @@ func TestConnectResetAfterClose(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestCurrentConnectedIncrement tests increment of the current
|
||||
// established and connected counters.
|
||||
func TestCurrentConnectedIncrement(t *testing.T) {
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
|
||||
// Set TCPTimeWaitTimeout to 1 seconds so that sockets are marked closed
|
||||
// after 1 second in TIME_WAIT state.
|
||||
tcpTimeWaitTimeout := 1 * time.Second
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPTimeWaitTimeoutOption(tcpTimeWaitTimeout)); err != nil {
|
||||
t.Fatalf("c.stack.SetTransportProtocolOption(tcp, tcpip.TCPTimeWaitTimeout(%d) failed: %s", tcpTimeWaitTimeout, err)
|
||||
}
|
||||
|
||||
c.CreateConnected(789, 30000, -1 /* epRcvBuf */)
|
||||
ep := c.EP
|
||||
c.EP = nil
|
||||
|
||||
if got := c.Stack().Stats().TCP.CurrentEstablished.Value(); got != 1 {
|
||||
t.Errorf("got stats.TCP.CurrentEstablished.Value() = %v, want = 1", got)
|
||||
}
|
||||
gotConnected := c.Stack().Stats().TCP.CurrentConnected.Value()
|
||||
if gotConnected != 1 {
|
||||
t.Errorf("got stats.TCP.CurrentConnected.Value() = %v, want = 1", gotConnected)
|
||||
}
|
||||
|
||||
ep.Close()
|
||||
|
||||
checker.IPv4(t, c.GetPacket(),
|
||||
checker.TCP(
|
||||
checker.DstPort(context.TestPort),
|
||||
checker.SeqNum(uint32(c.IRS)+1),
|
||||
checker.AckNum(790),
|
||||
checker.TCPFlags(header.TCPFlagAck|header.TCPFlagFin),
|
||||
),
|
||||
)
|
||||
c.SendPacket(nil, &context.Headers{
|
||||
SrcPort: context.TestPort,
|
||||
DstPort: c.Port,
|
||||
Flags: header.TCPFlagAck,
|
||||
SeqNum: 790,
|
||||
AckNum: c.IRS.Add(2),
|
||||
RcvWnd: 30000,
|
||||
})
|
||||
|
||||
if got := c.Stack().Stats().TCP.CurrentEstablished.Value(); got != 0 {
|
||||
t.Errorf("got stats.TCP.CurrentEstablished.Value() = %v, want = 0", got)
|
||||
}
|
||||
if got := c.Stack().Stats().TCP.CurrentConnected.Value(); got != gotConnected {
|
||||
t.Errorf("got stats.TCP.CurrentConnected.Value() = %v, want = %v", got, gotConnected)
|
||||
}
|
||||
|
||||
// Ack and send FIN as well.
|
||||
c.SendPacket(nil, &context.Headers{
|
||||
SrcPort: context.TestPort,
|
||||
DstPort: c.Port,
|
||||
Flags: header.TCPFlagAck | header.TCPFlagFin,
|
||||
SeqNum: 790,
|
||||
AckNum: c.IRS.Add(2),
|
||||
RcvWnd: 30000,
|
||||
})
|
||||
|
||||
// Check that the stack acks the FIN.
|
||||
checker.IPv4(t, c.GetPacket(),
|
||||
checker.PayloadLen(header.TCPMinimumSize),
|
||||
checker.TCP(
|
||||
checker.DstPort(context.TestPort),
|
||||
checker.SeqNum(uint32(c.IRS)+2),
|
||||
checker.AckNum(791),
|
||||
checker.TCPFlags(header.TCPFlagAck),
|
||||
),
|
||||
)
|
||||
|
||||
// Wait for the TIME-WAIT state to transition to CLOSED.
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
if got := c.Stack().Stats().TCP.CurrentEstablished.Value(); got != 0 {
|
||||
t.Errorf("got stats.TCP.CurrentEstablished.Value() = %v, want = 0", got)
|
||||
}
|
||||
if got := c.Stack().Stats().TCP.CurrentConnected.Value(); got != 0 {
|
||||
t.Errorf("got stats.TCP.CurrentConnected.Value() = %v, want = 0", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestClosingWithEnqueuedSegments tests handling of still enqueued segments
|
||||
// when the endpoint transitions to StateClose. The in-flight segments would be
|
||||
// re-enqueued to a any listening endpoint.
|
||||
|
||||
Reference in New Issue
Block a user