2026-05-13
Every time you've run netstat -s or watched a Grafana dashboard show "TCP segments retransmitted," you've consumed data that ultimately traces back to a small family of standardized counters. RFC 4022 is the document that defines what those counters mean, what they're called over SNMP, and how a network management station can ask any conforming device — a Cisco router, a Linux box, a printer — the same question and get a comparable answer.
It updates and obsoletes the original TCP MIB in RFC 2012 (1996) and, before that, RFC 1213 (1991). The 2005 revision modernized it for SMIv2, added IPv6 support via the InetAddress textual convention, and — importantly — split the connection table so that listening sockets and established connections live in separate rows you can actually iterate sensibly.
The problem it solves. Before the TCP-MIB, every vendor exposed TCP statistics differently. You could not write a single monitoring tool that asked "how many active opens has this device performed?" and get a uniform answer. SNMP needed a canonical object identifier (OID) tree for TCP, with precise semantics for each counter, so that tcpActiveOpens.0 meant the same thing on a Sun workstation and a Wellfleet router.
What's inside. The MIB defines scalar objects under 1.3.6.1.2.1.6 (the tcp subtree of mib-2):
tcpRtoAlgorithm, tcpRtoMin, tcpRtoMax — how this stack computes retransmission timeoutstcpActiveOpens, tcpPassiveOpens — outbound vs. inbound connection establishmentstcpAttemptFails, tcpEstabResets — failure counters that are gold for diagnosing flaky linkstcpCurrEstab — the gauge behind every "established connections" widgettcpInSegs, tcpOutSegs, tcpRetransSegs, tcpInErrs, tcpOutRsts — segment-level traffic statstcpHCInSegs, tcpHCOutSegs — 64-bit "high capacity" versions for fast links where 32-bit counters wrap in minutesThen there are two tables: tcpConnectionTable for active connections (indexed by local/remote address-and-port, with an address-type column so IPv4 and IPv6 coexist), and tcpListenerTable for sockets in LISTEN state. Each connection row carries a tcpConnectionState (1=closed … 11=timeWait) and a writable deleteTCB action that lets an operator forcibly kill a connection from a NMS — a feature few people realize SNMP supports.
Design decisions worth noticing. The split between connection and listener tables looks pedantic but solved a real bug: in the old MIB, a listener on 0.0.0.0:80 appeared as one row with a zero remote address, and you couldn't tell from the table whether it was idle or just unmatched. Separating them made the semantics unambiguous and made walks cheaper on busy servers. The InetAddress textual convention (from RFC 4001) means a single MIB handles both address families — the row index encodes the type explicitly rather than duplicating the whole table.
Why it still matters. Prometheus exporters, node_exporter's node_netstat_Tcp_* series, and most commercial NMS products either pull these OIDs directly or use names that are 1:1 mappings of the MIB. When you read about "TCP retransmission rate" in any monitoring system written in the last twenty years, the underlying definition is RFC 4022's tcpRetransSegs / tcpOutSegs. Linux's /proc/net/snmp file literally uses these names.
The quiet legacy: RFC 4022 is one of those documents nobody reads but everybody depends on. It's the reason cross-vendor network monitoring is even possible.
