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 {