You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.
I'm implementing UDP GSO for quic-go (tracking issue). Since quic-go does DPLPMTUD, a server will send packets with different sizes to different clients. Therefore, we can't just set a single packet size per UDP socket. Instead, we have to pass the desired packet size to the kernel with every sendmsg call.
In Go, this is done using the WriteMsgUDP function on the net.UDPConn. The size is encoded as a control message, which is passed in the oob byte parameter to that function:
The proof of concept works, as can be confirmed by running tcpdump (e.g. tcpdump host 22.214.171.124 -n -v -i eth0).
What did you see instead?
Serializing the control message has to be done by hand (see the getCmsg function in my PoC). The precise format of the control message is highly dependent on the architecture, and my PoC will only work on amd64 (see definition). Other architectures serialize this message slightly different, there are 41 (!) architecture-dependent ztypes_ files in the unix package that define the Cmsghdr.
x/sys/unix already provides a deserialization function (via ParseOneSocketControlMessage / ParseSocketControlMessage). It would it would provide some kind of serialization function that works on all architectures as well.
The text was updated successfully, but these errors were encountered:
Since this function is potentially called on every WriteMsgUDP call (although for the GSO use case, the result could obviously be cached for every packet size), it's essential that it doesn't cause any allocations. I therefore propose an append-style API:
func (Cmsghdr) Append(b byte, data byte) byte
x/sys/unix already supports most of what you need. See UnixRights for an example.
For your use case I believe it would be:
datalen:=2// your payload is a uint16, which is 2 bytesb:=make(byte, unix.CmsgSpace(datalen))
// UnixRights uses the private `data` method, but I *think* this achieves the same goal.offset:=unix.CmsgSpace(0)
Since your message is always the same length, you could choose to allocate the whole byte slice once, and just overwrite the uint16 payload each time.