pkg/tcpip/transport/tcp: add statistics for dropped connections

When the TCP forwarder ignores a connection due to having too many
in-flight connections, it's not easy to log a message or update a metric
for later debugging. Add a metric that will be incremented in this case
so that the user of the Forwarder can observe this.

Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
This commit is contained in:
Andrew Dunham
2023-07-17 15:07:55 -04:00
parent e672476d06
commit 057e0b7eae
5 changed files with 40 additions and 0 deletions
+1
View File
@@ -287,6 +287,7 @@ var Metrics = tcpip.Stats{
SegmentsAckedWithDSACK: mustCreateMetric("/netstack/tcp/segments_acked_with_dsack", "Number of segments for which DSACK was received."),
SpuriousRecovery: mustCreateMetric("/netstack/tcp/spurious_recovery", "Number of times the connection entered loss recovery spuriously."),
SpuriousRTORecovery: mustCreateMetric("/netstack/tcp/spurious_rto_recovery", "Number of times the connection entered RTO spuriously."),
ForwardMaxInFlightDrop: mustCreateMetric("/netstack/tcp/forward_max_in_flight_drop", "Number of connection requests dropped due to exceeding in-flight limit."),
},
UDP: tcpip.UDPStats{
PacketsReceived: mustCreateMetric("/netstack/udp/packets_received", "Number of UDP datagrams received via HandlePacket."),
+5
View File
@@ -2148,6 +2148,11 @@ type TCPStats struct {
// SpuriousRTORecovery is the number of spurious RTOs.
SpuriousRTORecovery *StatCounter
// ForwardMaxInFlightDrop is the number of connection requests that are
// dropped due to exceeding the maximum number of in-flight connection
// requests.
ForwardMaxInFlightDrop *StatCounter
}
// UDPStats collects UDP-specific stats.
+1
View File
@@ -88,6 +88,7 @@ func (f *Forwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.PacketB
// Ignore the segment if we're beyond the limit.
if len(f.inFlight) >= f.maxInFlight {
f.stack.Stats().TCP.ForwardMaxInFlightDrop.Increment()
return true
}
+2
View File
@@ -63,6 +63,7 @@ go_library(
"//pkg/tcpip/checker",
"//pkg/tcpip/header",
"//pkg/tcpip/seqnum",
"//pkg/tcpip/stack",
"//pkg/tcpip/transport/tcp",
"//pkg/tcpip/transport/tcp/testing/context",
"//pkg/waiter",
@@ -81,6 +82,7 @@ go_test(
"//pkg/tcpip/checker",
"//pkg/tcpip/header",
"//pkg/tcpip/seqnum",
"//pkg/tcpip/stack",
"//pkg/tcpip/transport/tcp",
"//pkg/tcpip/transport/tcp/testing/context",
],
@@ -169,6 +169,37 @@ func TestForwarderFailedConnect(t *testing.T) {
}
}
func TestForwarderDroppedStats(t *testing.T) {
const maxPayload = 100
const mtu = 1200
c := context.New(t, mtu)
defer c.Cleanup()
s := c.Stack()
const maxInFlight = 2
f := tcp.NewForwarder(s, 65536, maxInFlight, func(r *tcp.ForwarderRequest) {
// Complete all requests without doing anything
r.Complete(false)
})
s.SetTransportProtocolHandler(tcp.ProtocolNumber, f.HandlePacket)
for i := 0; i < maxInFlight*10; i++ {
iss := seqnum.Value(context.TestInitialSequenceNumber + i)
c.SendPacket(nil, &context.Headers{
SrcPort: uint16(context.TestPort + i),
DstPort: context.StackPort,
Flags: header.TCPFlagSyn,
SeqNum: iss,
RcvWnd: 30000,
})
}
// Verify that we got some ignored packets
if curr := s.Stats().TCP.ForwardMaxInFlightDrop.Value(); curr == 0 {
t.Errorf("Expected at least one dropped connection")
}
}
func TestMain(m *testing.M) {
refs.SetLeakMode(refs.LeaksPanic)
code := m.Run()