TcpInfo, an abstraction layer to capture and access TCP state
Summary: An cross-platform abstraction layer for capturing current TCP and congestion control state. Fetches information from four different resources: - `TCP_INFO` (state of TCP) - `TCP_CONGESTION` (name of congestion control algorithm) - `TCP_CC_INFO` (details for a given congestion control algorithm) - `SIOCOUTQ`/`SIOCINQ` (socket buffers) `TcpInfo` is designed to solve two problems: **(1) `TcpInfo` unblocks use of the latest `tcp_info` struct and related structs.** As of 2020, the `tcp_info` struct shipped with glibc (sysdeps/gnu/netinet/tcp.h) has not been updated since 2007 due to compatibility concerns; see commit titled "Update netinet/tcp.h from Linux 4.18" in glibc repository. This creates scenarios where fields that have long been available in the kernel ABI cannot be accessed. Even if glibc does eventually update the `tcp_info` shipped, we don't want to be limited to their update cycle. `TcpInfo` solves this in two ways: - First, `TcpInfoTypes.h` contains a copy of the latest `tcp_info` struct for Linux, and `TcpInfo` always uses this struct for lookups; this decouples `TcpInfo` from glibc's / the platform's `tcp_info`. - Second, `TcpInfo` determines which fields in the struct are populated (and thus valid) based on the number of bytes the kernel ABI copies into the struct during the corresponding getsockopt operation. When a field is accessed through `getFieldAsOptUInt64` or through an accessor, `TcpInfo` returns an empty optional if the field is unavailable at run-time. In this manner, `TcpInfo` enables the latest struct to always be used while ensuring that programs can determine at runtime which fields are available for use --- there's no risk of a program assuming that a field is valid when it in fact was never initialized/set by the ABI. **(2) `TcpInfo` abstracts platform differences while still keeping details available.** The `tcp_info` structure varies significantly between Apple and Linux. `TcpInfo` exposes a subset of `tcp_info` and other fields through accessors that hide these differences, and reduce potential errors (e.g., Apple stores srtt in milliseconds, Linux stores in microseconds, `TcpInfo::srtt` does the conversions needed to always return in microseconds). When a field is unavailable on a platform, the accessor returns an empty optional. In parallel, the underlying structures remain accessible and can be safely accessed through the appropriate `getFieldAsOptUInt64(...)`. This enables platform-specific code to have full access to the underlying structure while also benefiting from `TcpInfo`'s knowledge of whether a given field was populated by the ABI at run-time. Support for FreeBSD will be added in a subsequent diff. Differential Revision: D22134355 fbshipit-source-id: accae8762aa88c187cc473b8121df901c6ffb456
Showing
folly/net/TcpInfo.cpp
0 → 100644
folly/net/TcpInfo.h
0 → 100644
folly/net/TcpInfoTypes.h
0 → 100644
Please register or sign in to comment