net/batching: clarify & simplify single packet read limitations
ReadFromUDPAddrPort worked if UDP GRO was unsupported, but we don't actually want attempted usage, nor does any exist today. Future work on tailscale/corp#37679 would have required more complexity in this method, vs clarifying the API intents. Updates tailscale/corp#37679 Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
committed by
Jordan Whited
parent
70de111394
commit
607d01cdae
+11
-1
@@ -19,14 +19,24 @@ var (
|
||||
_ ipv6.Message = ipv4.Message{}
|
||||
)
|
||||
|
||||
// Conn is a nettype.PacketConn that provides batched i/o using
|
||||
// Conn is a [nettype.PacketConn] that provides batched i/o using
|
||||
// platform-specific optimizations, e.g. {recv,send}mmsg & UDP GSO/GRO.
|
||||
//
|
||||
// Conn does not support single packet reads (see ReadFromUDPAddrPort docs). It
|
||||
// is the caller's responsibility to use the appropriate read API where a
|
||||
// [nettype.PacketConn] has been upgraded to support batched i/o.
|
||||
//
|
||||
// Conn originated from (and is still used by) magicsock where its API was
|
||||
// strongly influenced by [wireguard-go/conn.Bind] constraints, namely
|
||||
// wireguard-go's ownership of packet memory.
|
||||
type Conn interface {
|
||||
nettype.PacketConn
|
||||
// ReadFromUDPAddrPort always returns an error, as UDP GRO is incompatible
|
||||
// with single packet reads. A single datagram may be multiple, coalesced
|
||||
// datagrams, and this API lacks the ability to pass that context.
|
||||
//
|
||||
// TODO: consider detaching Conn from [nettype.PacketConn]
|
||||
ReadFromUDPAddrPort([]byte) (int, netip.AddrPort, error)
|
||||
// ReadBatch reads messages from [Conn] into msgs. It returns the number of
|
||||
// messages the caller should evaluate for nonzero len, as a zero len
|
||||
// message may fall on either side of a nonzero.
|
||||
|
||||
@@ -61,16 +61,7 @@ type linuxBatchingConn struct {
|
||||
}
|
||||
|
||||
func (c *linuxBatchingConn) ReadFromUDPAddrPort(p []byte) (n int, addr netip.AddrPort, err error) {
|
||||
if c.rxOffload {
|
||||
// UDP_GRO is opt-in on Linux via setsockopt(). Once enabled you may
|
||||
// receive a "monster datagram" from any read call. The ReadFrom() API
|
||||
// does not support passing the GSO size and is unsafe to use in such a
|
||||
// case. Other platforms may vary in behavior, but we go with the most
|
||||
// conservative approach to prevent this from becoming a footgun in the
|
||||
// future.
|
||||
return 0, netip.AddrPort{}, errors.New("rx UDP offload is enabled on this socket, single packet reads are unavailable")
|
||||
}
|
||||
return c.pc.ReadFromUDPAddrPort(p)
|
||||
return 0, netip.AddrPort{}, errors.New("single packet reads are unsupported")
|
||||
}
|
||||
|
||||
func (c *linuxBatchingConn) SetDeadline(t time.Time) error {
|
||||
|
||||
Reference in New Issue
Block a user