diff --git a/conn/conn.go b/conn/conn.go index a1541a3..5234ddb 100644 --- a/conn/conn.go +++ b/conn/conn.go @@ -138,6 +138,11 @@ type ListenerSocketOptions struct { // Available on platforms supported by Go std's MPTCP implementation. MultipathTCP bool + // UDPGenericReceiveOffload enables UDP Generic Receive Offload (GRO) on the listener. + // + // Available on Linux and Windows. + UDPGenericReceiveOffload bool + // ReceivePacketInfo enables the reception of packet information control messages on the listener. // // Available on Linux, macOS, and Windows. diff --git a/conn/conn_linux.go b/conn/conn_linux.go index aae2a6c..8d406c3 100644 --- a/conn/conn_linux.go +++ b/conn/conn_linux.go @@ -51,6 +51,10 @@ func setTCPUserTimeout(fd, msecs int) error { return nil } +func setUDPGenericReceiveOffload(fd int) { + _ = unix.SetsockoptInt(fd, unix.IPPROTO_UDP, unix.UDP_GRO, 1) +} + func setTransparent(fd int, network string) error { switch network { case "tcp4", "udp4": @@ -162,6 +166,7 @@ func (lso ListenerSocketOptions) buildSetFns() setFuncSlice { appendSetReusePortFunc(lso.ReusePort). appendSetTransparentFunc(lso.Transparent). appendSetPMTUDFunc(lso.PathMTUDiscovery). + appendSetUDPGenericReceiveOffloadFunc(lso.UDPGenericReceiveOffload). appendSetRecvPktinfoFunc(lso.ReceivePacketInfo). appendSetRecvOrigDstAddrFunc(lso.ReceiveOriginalDestAddr) } diff --git a/conn/conn_udpgro.go b/conn/conn_udpgro.go new file mode 100644 index 0000000..d185b3c --- /dev/null +++ b/conn/conn_udpgro.go @@ -0,0 +1,13 @@ +//go:build linux || windows + +package conn + +func (fns setFuncSlice) appendSetUDPGenericReceiveOffloadFunc(gro bool) setFuncSlice { + if gro { + return append(fns, func(fd int, _ string) error { + setUDPGenericReceiveOffload(fd) + return nil + }) + } + return fns +} diff --git a/conn/conn_windows.go b/conn/conn_windows.go index 6e1be4d..28901e5 100644 --- a/conn/conn_windows.go +++ b/conn/conn_windows.go @@ -41,6 +41,11 @@ func setPMTUD(fd int, network string) error { return nil } +func setUDPGenericReceiveOffload(fd int) { + // Both quinn and msquic set this to 65535. + _ = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_UDP, windows.UDP_RECV_MAX_COALESCED_SIZE, 65535) +} + func setRecvPktinfo(fd int, network string) error { // Set IP_PKTINFO for both v4 and v6. if err := windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, windows.IP_PKTINFO, 1); err != nil { @@ -63,6 +68,7 @@ func setRecvPktinfo(fd int, network string) error { func (lso ListenerSocketOptions) buildSetFns() setFuncSlice { return setFuncSlice{}. appendSetPMTUDFunc(lso.PathMTUDiscovery). + appendSetUDPGenericReceiveOffloadFunc(lso.UDPGenericReceiveOffload). appendSetRecvPktinfoFunc(lso.ReceivePacketInfo) }