Support /proc/net/dev, /proc/net/route, /proc/net/snmp Support for /proc/net/dev, /proc/net/route, and /proc/net/snmp [1]. This should enable the use of tools such as route[2]. [1] https://tools.ietf.org/html/rfc2013 [2] http://man7.org/linux/man-pages/man8/route.8.html PiperOrigin-RevId: 276380008
diff --git a/tcpip/tcpip.go b/tcpip/tcpip.go index 5dbfa42..3a8e56e 100644 --- a/tcpip/tcpip.go +++ b/tcpip/tcpip.go
@@ -673,6 +673,11 @@ s.IncrementBy(1) } +// Decrement minuses one to the counter. +func (s *StatCounter) Decrement() { + s.IncrementBy(^uint64(0)) +} + // Value returns the current value of the counter. func (s *StatCounter) Value() uint64 { return atomic.LoadUint64(&s.count) @@ -881,6 +886,15 @@ // successfully via Listen. PassiveConnectionOpenings *StatCounter + // CurrentEstablished is the number of TCP connections for which the + // current state is either ESTABLISHED or CLOSE-WAIT. + CurrentEstablished *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. + EstablishedResets *StatCounter + // ListenOverflowSynDrop is the number of times the listen queue overflowed // and a SYN was dropped. ListenOverflowSynDrop *StatCounter
diff --git a/tcpip/transport/tcp/accept.go b/tcpip/transport/tcp/accept.go index c287325..72d711b 100644 --- a/tcpip/transport/tcp/accept.go +++ b/tcpip/transport/tcp/accept.go
@@ -297,6 +297,7 @@ return nil, err } ep.mu.Lock() + ep.stack.Stats().TCP.CurrentEstablished.Increment() ep.state = StateEstablished ep.mu.Unlock() @@ -519,6 +520,7 @@ n.tsOffset = 0 // Switch state to connected. + n.stack.Stats().TCP.CurrentEstablished.Increment() n.state = StateEstablished // Do the delivery in a separate goroutine so
diff --git a/tcpip/transport/tcp/connect.go b/tcpip/transport/tcp/connect.go index d4625dd..1933f75 100644 --- a/tcpip/transport/tcp/connect.go +++ b/tcpip/transport/tcp/connect.go
@@ -805,6 +805,10 @@ func (e *endpoint) resetConnectionLocked(err *tcpip.Error) { // Only send a reset if the connection is being aborted for a reason // other than receiving a reset. + if e.state == StateEstablished || e.state == StateCloseWait { + e.stack.Stats().TCP.EstablishedResets.Increment() + e.stack.Stats().TCP.CurrentEstablished.Decrement() + } e.state = StateError e.HardError = err if err != tcpip.ErrConnectionReset { @@ -975,6 +979,8 @@ e.lastErrorMu.Unlock() e.mu.Lock() + e.stack.Stats().TCP.EstablishedResets.Increment() + e.stack.Stats().TCP.CurrentEstablished.Decrement() e.state = StateError e.HardError = err @@ -1005,7 +1011,10 @@ // Tell waiters that the endpoint is connected and writable. e.mu.Lock() - e.state = StateEstablished + if e.state != StateEstablished { + e.stack.Stats().TCP.CurrentEstablished.Increment() + e.state = StateEstablished + } drained := e.drainDone != nil e.mu.Unlock() if drained { @@ -1166,6 +1175,8 @@ // Mark endpoint as closed. e.mu.Lock() if e.state != StateError { + e.stack.Stats().TCP.EstablishedResets.Increment() + e.stack.Stats().TCP.CurrentEstablished.Decrement() e.state = StateClose } // Lock released below.
diff --git a/tcpip/transport/tcp/endpoint.go b/tcpip/transport/tcp/endpoint.go index 3a4ece4..e667201 100644 --- a/tcpip/transport/tcp/endpoint.go +++ b/tcpip/transport/tcp/endpoint.go
@@ -1729,6 +1729,7 @@ e.segmentQueue.mu.Unlock() e.snd.updateMaxPayloadSize(int(e.route.MTU()), 0) e.state = StateEstablished + e.stack.Stats().TCP.CurrentEstablished.Increment() } if run {
diff --git a/tcpip/transport/tcp/snd.go b/tcpip/transport/tcp/snd.go index fa616b9..d4bad63 100644 --- a/tcpip/transport/tcp/snd.go +++ b/tcpip/transport/tcp/snd.go
@@ -674,6 +674,7 @@ default: s.ep.state = StateFinWait1 } + s.ep.stack.Stats().TCP.CurrentEstablished.Decrement() s.ep.mu.Unlock() } else { // We're sending a non-FIN segment.