gfe-relnote: Introduce kDefaultUdpPacketControlBufferSize and use it in QuicPacketReader as the control buffer size. No behavior change, not protected. Why? I need to remove kCmsgSpaceForReadPacket, which is defined in quic_socket_utils.h. Merge note: Please define kCmsgSpaceForGooglePacketHeaderImpl=0 in Chromium's quic_udp_socket_platform_impl.h. PiperOrigin-RevId: 291940730 Change-Id: I0e7d9652e42218b06ce535b2d7297dda88971341
diff --git a/quic/core/quic_packet_reader.h b/quic/core/quic_packet_reader.h index 623f01b..e4961b9 100644 --- a/quic/core/quic_packet_reader.h +++ b/quic/core/quic_packet_reader.h
@@ -94,7 +94,8 @@ #endif struct QUIC_EXPORT_PRIVATE ReadBuffer { QUIC_CACHELINE_ALIGNED char - control_buffer[kCmsgSpaceForReadPacket]; // For ancillary data. + control_buffer[kDefaultUdpPacketControlBufferSize]; // For ancillary + // data. QUIC_CACHELINE_ALIGNED char packet_buffer[kMaxIncomingPacketSize]; }; // Latched value of --quic_remove_quic_socket_utils_from_packet_reader.
diff --git a/quic/core/quic_udp_socket.h b/quic/core/quic_udp_socket.h index 8be9e57..04f8435 100644 --- a/quic/core/quic_udp_socket.h +++ b/quic/core/quic_udp_socket.h
@@ -25,6 +25,8 @@ const QuicUdpSocketFd kQuicInvalidSocketFd = -1; #endif +const size_t kDefaultUdpPacketControlBufferSize = 512; + enum class QuicUdpPacketInfoBit : uint8_t { DROPPED_PACKETS = 0, // Read V4_SELF_IP, // Read @@ -205,7 +207,8 @@ // |result->packet_buffer.buffer_len| is set to the // packet length on a successful return. // result->control_buffer: The control buffer, used by ReadPacket internally. - // It is recommended to be at least 512 bytes. + // It is recommended to be + // |kDefaultUdpPacketControlBufferSize| bytes. // result->ok: True iff a packet is successfully received. // // If |*result| is reused for subsequent ReadPacket() calls, caller needs to
diff --git a/quic/core/quic_udp_socket_posix.cc b/quic/core/quic_udp_socket_posix.cc index 1141c1c..b6c58cd 100644 --- a/quic/core/quic_udp_socket_posix.cc +++ b/quic/core/quic_udp_socket_posix.cc
@@ -29,6 +29,34 @@ namespace quic { namespace { + +#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21) +#define QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING 1 +// This is the structure that SO_TIMESTAMPING fills into the cmsg header. +// It is well-defined, but does not have a definition in a public header. +// See https://www.kernel.org/doc/Documentation/networking/timestamping.txt +// for more information. +struct LinuxSoTimestamping { + // The converted system time of the timestamp. + struct timespec systime; + // Deprecated; serves only as padding. + struct timespec hwtimetrans; + // The raw hardware timestamp. + struct timespec hwtimeraw; +}; +const size_t kCmsgSpaceForRecvTimestamp = + CMSG_SPACE(sizeof(LinuxSoTimestamping)); +#else +const size_t kCmsgSpaceForRecvTimestamp = 0; +#endif + +const size_t kMinCmsgSpaceForRead = + CMSG_SPACE(sizeof(uint32_t)) // Dropped packet count + + CMSG_SPACE(sizeof(in_pktinfo)) // V4 Self IP + + CMSG_SPACE(sizeof(in6_pktinfo)) // V6 Self IP + + kCmsgSpaceForRecvTimestamp + CMSG_SPACE(sizeof(int)) // TTL + + kCmsgSpaceForGooglePacketHeader; + QuicUdpSocketFd CreateNonblockingSocket(int address_family) { #if defined(__linux__) && defined(SOCK_NONBLOCK) @@ -109,24 +137,11 @@ } #endif -#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21) +#if defined(QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING) { - // This is the structure that SO_TIMESTAMPING fills into the cmsg header. - // It is well-defined, but does not have a definition in a public header. - // See https://www.kernel.org/doc/Documentation/networking/timestamping.txt - // for more information. - struct LinuxTimestamping { - // The converted system time of the timestamp. - struct timespec systime; - // Deprecated; serves only as padding. - struct timespec hwtimetrans; - // The raw hardware timestamp. - struct timespec hwtimeraw; - }; - if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::RECV_TIMESTAMP)) { - LinuxTimestamping* linux_ts = - reinterpret_cast<LinuxTimestamping*>(CMSG_DATA(cmsg)); + LinuxSoTimestamping* linux_ts = + reinterpret_cast<LinuxSoTimestamping*>(CMSG_DATA(cmsg)); timespec* ts = &linux_ts->systime; int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) + (static_cast<int64_t>(ts->tv_nsec) / 1000); @@ -225,6 +240,10 @@ QuicUdpSocketFd QuicUdpSocketApi::Create(int address_family, int receive_buffer_size, int send_buffer_size) { + // DCHECK here so the program exits early(before reading packets) in debug + // mode. This should have been a static_assert, however it can't be done on + // ios/osx because CMSG_SPACE isn't a constant expression there. + DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead); QuicUdpSocketFd fd = CreateNonblockingSocket(address_family); if (fd == kQuicInvalidSocketFd) { @@ -359,6 +378,8 @@ BufferSpan& control_buffer = result->control_buffer; QuicUdpPacketInfo* packet_info = &result->packet_info; + DCHECK_GE(control_buffer.buffer_len, kMinCmsgSpaceForRead); + struct iovec iov = {packet_buffer.buffer, packet_buffer.buffer_len}; struct sockaddr_storage raw_peer_address; @@ -461,6 +482,8 @@ hdr->msg_flags = 0; hdr->msg_control = (*results)[i].control_buffer.buffer; hdr->msg_controllen = (*results)[i].control_buffer.buffer_len; + + DCHECK_GE(hdr->msg_controllen, kMinCmsgSpaceForRead); } // If MSG_TRUNC is set on Linux, recvmmsg will return the real packet size in // |hdrs[i].msg_len| even if packet buffer is too small to receive it.
diff --git a/quic/platform/api/quic_udp_socket_platform_api.h b/quic/platform/api/quic_udp_socket_platform_api.h index 78d35f8..2b1f9c3 100644 --- a/quic/platform/api/quic_udp_socket_platform_api.h +++ b/quic/platform/api/quic_udp_socket_platform_api.h
@@ -9,6 +9,9 @@ namespace quic { +const size_t kCmsgSpaceForGooglePacketHeader = + kCmsgSpaceForGooglePacketHeaderImpl; + inline bool GetGooglePacketHeadersFromControlMessage( struct ::cmsghdr* cmsg, char** packet_headers,