golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.98k stars 17.67k forks source link

net: document PacketConn IO operations in relation to packet sizes #18056

Open dsnet opened 7 years ago

dsnet commented 7 years ago

The current phrasing on PacketConn.ReadFrom and PacketConn.WriteTo is:

ReadFrom reads a packet from the connection, copying the payload into b. It returns the number of bytes copied into b and the return address that was on the packet. ReadFrom can be made to time out and return an Error with Timeout() == true after a fixed time limit; see SetDeadline and SetReadDeadline.

and

WriteTo writes a packet with payload b to addr. WriteTo can be made to time out and return an Error with Timeout() == true after a fixed time limit; see SetDeadline and SetWriteDeadline. On packet-oriented connections, write timeouts are rare.

What is the expected behavior of ReadFrom when the buffer provided is not large enough to read the entire packet? Does the remaining payload get dropped? Does the next call to ReadFrom finish off the packet?

On the flip-side, what happens when the buffer provided to WriteTo is larger than the MTU. Should the method implicitly chunk the input into multiple packet-sized chunks?

\cc @mikioh

mikioh commented 7 years ago

What is the expected behavior of ...

It indeed depends on the underlying protocol and its implementation attaching to the PacketConn interface. Also the underlying protocol affects the behavior of IO operations not only for PacketConn but for Conn interface. We need to update the documentation on Conn interface too for a Conn created by Dial("udp", ...).

when the buffer provided is not large enough ...

Almost all the implementations of connectionless datagram (e.g. UDP) or connection-oriented chunk protocols (e.g. SCTP or AF_UNIX+SOCK_SEQPACKET) allow only datagram (or chunk) basis IO calls. A read (or variant such as recv, recvfrom or recvmsg) system call waits for datagram arrival and copies the payload from the datagram as much as possible, and discards remaining portion by default when the supplied destination space is not enough large. A few platforms support an option which is able to retain the remaining portion until the next read call, but we probably don't need to state such optional behavior.

what happens when the buffer ... is larger than the MTU ...

When the stack, say UDP over IP, supports datagram fragmentation and reassembly features, the stack takes care of it and the IP datagrams on the wire will be a series of fragmented ones. Otherwise a write (or variant such as send, sendto or sendmsg) system call may return an error. The transmission process of datagrams refers to various kernel states such as maximum datagram size for UDP and metrics like link and path MTU values, and the behavior of transmission buffer exhaustion is different between connectionless datagram protocols and connection-oriented chunk protocols. In general a write call may return various errors depend on the circumstances.

gopherbot commented 6 years ago

Change https://golang.org/cl/92475 mentions this issue: net: fix UDPConn readers to return truncated payload size instead of 0