/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <chrono> #include <system_error> #include <folly/Expected.h> #include <folly/Optional.h> #include <folly/String.h> #include <folly/net/NetOpsDispatcher.h> #include <folly/net/NetworkSocket.h> #include <folly/net/TcpInfoTypes.h> namespace folly { /** * 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) * * To save space, the structure only allocates fields for which the underlying * platform supports lookups. For instance, if TCP_CONGESTION is not supported, * then the TcpInfo structure will not have fields to store the CC name / type. * * This abstraction layer solves two problems: * * 1. It unblocks use of the latest tcp_info structs 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. * * folly::TcpInfo solves this in two ways: * - First, TcpInfoTypes.h contains a copy of the latest tcp_info struct * for Linux, and folly::TcpInfo always uses this struct for lookups; * this decouples TcpInfo from glibc's / the platform's tcp_info. * * - Second, folly::TcpInfo determines which fields in the struct the * kernel ABI populated (and thus which fields are 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, folly::TcpInfo * returns an empty optional if the field is unavailable at run-time. * In this manner, folly::TcpInfo enables the latest struct to always * be used while ensuring that programs can determine at run-time * 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. Eliminates platform differences while still retaining details. * * The tcp_info structure varies significantly between Apple and Linux. * folly::TcpInfo exposes a subset of tcp_info and other fields through * accessors that abstract these differences, and reduce potential errors * (e.g., Apple stores srtt in milliseconds, Linux stores 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 structure * while also benefiting from folly::TcpInfo's knowledge of whether a * given field was populated by the ABI at run-time. */ struct TcpInfo { … }; } // namespace folly