Count resets and segments sent in sendTCP.
This requires adding a method to stack.Route to access the referenced
network endpoint's Stats struct, but now covers SYN, RST, and shutdown segments
that weren't counted before, along with resets sent via
HandleUnknownDestinationPacket.
Change-Id: I206b66eee07489e9588974664d7a0288b922bef2
diff --git a/tcpip/stack/route.go b/tcpip/stack/route.go
index fef7daf..f175556 100644
--- a/tcpip/stack/route.go
+++ b/tcpip/stack/route.go
@@ -60,6 +60,12 @@
return r.ref.ep.MaxHeaderLength()
}
+// MutableStats returns a mutable copy of the referenced endpoint's Stats
+// struct, for stats updates where we only have a reference to the Route.
+func (r *Route) MutableStats() *tcpip.Stats {
+ return r.ref.nic.stack.MutableStats()
+}
+
// PseudoHeaderChecksum forwards the call to the network endpoint's
// implementation.
func (r *Route) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber) uint16 {
diff --git a/tcpip/tcpip.go b/tcpip/tcpip.go
index cde2a55..029a6c7 100644
--- a/tcpip/tcpip.go
+++ b/tcpip/tcpip.go
@@ -428,11 +428,7 @@
// InvalidSegmentsReceived is the number of TCP segments received that
// the transport layer could not parse.
InvalidSegmentsReceived uint64
- // SegmentsSent is the number of TCP segments sent from the transport
- // layer. Excludes shutdown, reset, and syn segments, because those
- // segments are sent via stack.Route, which writes directly to the network
- // endpoint (bypassing the transport endpoint and its associated Stats
- // struct completely).
+ // SegmentsSent is the number of TCP segments sent.
SegmentsSent uint64
// ResetsSent is the number of TCP resets sent.
ResetsSent uint64
diff --git a/tcpip/transport/tcp/connect.go b/tcpip/transport/tcp/connect.go
index e47fe32..3368cbf 100644
--- a/tcpip/transport/tcp/connect.go
+++ b/tcpip/transport/tcp/connect.go
@@ -449,6 +449,11 @@
tcp.SetChecksum(^tcp.CalculateChecksum(xsum, length))
+ atomic.AddUint64(&r.MutableStats().TCP.SegmentsSent, 1)
+ if (flags & flagRst) != 0 {
+ atomic.AddUint64(&r.MutableStats().TCP.ResetsSent, 1)
+ }
+
return r.WritePacket(&hdr, data, ProtocolNumber, ttl)
}
@@ -483,16 +488,16 @@
tcp.SetChecksum(^tcp.CalculateChecksum(xsum, length))
+ atomic.AddUint64(&r.MutableStats().TCP.SegmentsSent, 1)
+ if (flags & flagRst) != 0 {
+ atomic.AddUint64(&r.MutableStats().TCP.ResetsSent, 1)
+ }
+
return r.WritePacket(&hdr, data, ProtocolNumber, ttl)
}
// sendRaw sends a TCP segment to the endpoint's peer.
func (e *endpoint) sendRaw(data buffer.View, flags byte, seq, ack seqnum.Value, rcvWnd seqnum.Size) *tcpip.Error {
- atomic.AddUint64(&e.stack.MutableStats().TCP.SegmentsSent, 1)
-
- if (flags & flagRst) != 0 {
- atomic.AddUint64(&e.stack.MutableStats().TCP.ResetsSent, 1)
- }
if e.sendTSOk {
// Embed the timestamp if timestamp has been enabled.
//
diff --git a/tcpip/transport/tcp/tcp_test.go b/tcpip/transport/tcp/tcp_test.go
index 95de8bc..cd2a70e 100644
--- a/tcpip/transport/tcp/tcp_test.go
+++ b/tcpip/transport/tcp/tcp_test.go
@@ -150,7 +150,8 @@
defer c.Cleanup()
stats := c.Stack().MutableStats()
- expected := stats.TCP.SegmentsSent + 1
+ // SYN and ACK
+ expected := stats.TCP.SegmentsSent + 2
c.CreateConnected(789, 30000, nil)
if actual := stats.TCP.SegmentsSent; actual != expected {