Add Pigeon USPS GSO Support via quic::PigeonWriter. This CL adds quic::PigeonWriter and quic::PigeonSocket classes, with extensive unit tests. It refactors the old gfe2::RawSocket into a quic::RawSocketInterface and gfe2::RawQuicWriter into quic::RawPacketWriterBase. All gfe/gfe2/quic classes continue to work in the same way as before, only refactored. The changes in the CL are transparent to gfe/gfe2/quic. The new PigeonSocket uses a BufferAllocator, which is a freelist of shared memory buffers of size 2048 bytes. The socket can externally share shared memory buffers via PigeonSocket::AcquireSegmentBufferFromSharedMemory(). The PigeonWriter uses this to support "GetNextWriteLocation()" for the QUIC connection to serialize packets directly into shared memory. This eliminates a memcpy() in the critical path. The PigeonWriter and PigeonSocket classes support GSO by batching up to --quic_pigeon_socket_max_gso_segments number of segments per write. The PigeonWriter can also be used in pass-through mode by disabling GSO via flag --quic_pigeon_writer_enable_udp_gso. If flag --ustreamer_quic_use_new_pigeon_writer is true, and the egress method is USPS, then Ustreamer will create the new quic::PigeonWriter rather than gfe2::RawQuicWriter. gfe-relnote: GFE related changes refactors gfe's PigeonSocketWriteBlockHandler to net/quic/pigeon_socket.h PiperOrigin-RevId: 304279221 Change-Id: I919f8a7b8f2f039f07c078f11f2413dd6f39e12a
diff --git a/quic/core/quic_packet_writer.h b/quic/core/quic_packet_writer.h index 5f6b681..bd10523 100644 --- a/quic/core/quic_packet_writer.h +++ b/quic/core/quic_packet_writer.h
@@ -78,6 +78,26 @@ // // Options must be either null, or created for the particular QuicPacketWriter // implementation. Options may be ignored, depending on the implementation. + // + // Some comment about memory management if |buffer| was previously acquired + // by a call to "GetNextWriteLocation()": + // + // a) When WRITE_STATUS_OK is returned, the caller expects the writer owns the + // packet buffers and they will be released when the write finishes. + // + // b) When this function returns any status >= WRITE_STATUS_ERROR, the caller + // expects the writer releases the buffer (if needed) before the function + // returns. + // + // c) When WRITE_STATUS_BLOCKED is returned, the caller makes a copy of the + // buffer and will retry after unblock, so if |payload| is allocated from + // GetNextWriteLocation(), it + // 1) needs to be released before return, and + // 2) the content of |payload| should not change after return. + // + // d) When WRITE_STATUS_BLOCKED_DATA_BUFFERED is returned, the caller expects + // 1) the writer owns the packet buffers, and 2) the writer will re-send the + // packet when it unblocks. virtual WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, @@ -121,9 +141,13 @@ // Try send all buffered packets. // - Return WriteResult(WRITE_STATUS_OK, <bytes_flushed>) if all buffered // packets were sent successfully. - // - Return WRITE_STATUS_BLOCKED, or an error status, if the underlying socket - // is blocked or returned an error while sending. Some packets may have been - // sent, packets not sent will stay in the internal buffer. + // - Return WRITE_STATUS_BLOCKED if the underlying socket is blocked while + // sending. Some packets may have been sent, packets not sent will stay in + // the internal buffer. + // - Return a status >= WRITE_STATUS_ERROR if an error was encuontered while + // sending. As this is not a re-tryable error, any batched packets which + // were on memory acquired via GetNextWriteLocation() should be released and + // the batch should be dropped. virtual WriteResult Flush() = 0; };
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h index b8a77a9..76d3bab 100644 --- a/quic/core/quic_types.h +++ b/quic/core/quic_types.h
@@ -148,6 +148,9 @@ // Number of packets dropped as a result of this write. // Only used by batch writers. Otherwise always 0. uint16_t dropped_packets = 0; + // TODO(wub): In some cases, WRITE_STATUS_ERROR may set an error_code and + // WRITE_STATUS_BLOCKED_DATA_BUFFERED may set bytes_written. This may need + // some cleaning up so that perhaps both values can be set and valid. union { int bytes_written; // only valid when status is WRITE_STATUS_OK int error_code; // only valid when status is WRITE_STATUS_ERROR