fix(listener): keep *net.UDPConn visible to quic-go for GSO/GRO
The quic and wt (WebTransport) listeners wrap the raw UDP socket with net.PacketConn metrics/stats/admission/limiter wrappers before handing it to quic-go. WrapPacketConn returns a plain net.PacketConn, which hides the underlying *net.UDPConn. quic-go probes the conn for OOBCapablePacketConn (SyscallConn, SetReadBuffer, ReadMsgUDP, WriteMsgUDP); behind the wrapper that probe fails, so quic-go disables its kernel offloads and cannot size its receive buffer. Switch the non-cipher path of both listeners to WrapUDPConn variants, which forward SyscallConn/SetReadBuffer/ReadMsgUDP/WriteMsgUDP down to the underlying *net.UDPConn, so quic-go sees an OOBCapablePacketConn and keeps GSO/GRO + buffer sizing. The same metrics/stats/admission/ limiting still apply. The quic listener's cipher path keeps the net.PacketConn wrappers, since CipherPacketConn is not OOB-capable. +48% throughput (1.80 → 2.69 Gbit/s single-stream, loopback iperf3). The quic-go receive-buffer warning is gone.
This commit is contained in:
2 files changed
+31
-16
No files matched your search
@@ -74,10 +74,12 @@ func (l *wtListener) Init(md md.Metadata) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pc = metrics.WrapPacketConn(l.options.Service, pc)
|
pc = metrics.WrapUDPConn(l.options.Service, pc)
|
||||||
pc = stats.WrapPacketConn(pc, l.options.Stats)
|
if l.options.Stats != nil {
|
||||||
pc = admission.WrapPacketConn(l.options.Admission, pc)
|
pc = stats.WrapUDPConn(pc, l.options.Stats)
|
||||||
pc = limiter_wrapper.WrapPacketConn(
|
}
|
||||||
|
pc = admission.WrapUDPConn(l.options.Admission, pc)
|
||||||
|
pc = limiter_wrapper.WrapUDPConn(
|
||||||
pc,
|
pc,
|
||||||
l.options.TrafficLimiter,
|
l.options.TrafficLimiter,
|
||||||
traffic_limiter.ServiceLimitKey,
|
traffic_limiter.ServiceLimitKey,
|
||||||
|
|||||||
+25
-12
@@ -70,20 +70,33 @@ func (l *quicListener) Init(md md.Metadata) (err error) {
|
|||||||
}
|
}
|
||||||
if l.md.cipherKey != nil {
|
if l.md.cipherKey != nil {
|
||||||
conn = quic_util.CipherPacketConn(conn, l.md.cipherKey)
|
conn = quic_util.CipherPacketConn(conn, l.md.cipherKey)
|
||||||
|
conn = metrics.WrapPacketConn(l.options.Service, conn)
|
||||||
|
conn = stats.WrapPacketConn(conn, l.options.Stats)
|
||||||
|
conn = admission.WrapPacketConn(l.options.Admission, conn)
|
||||||
|
conn = limiter_wrapper.WrapPacketConn(
|
||||||
|
conn,
|
||||||
|
l.options.TrafficLimiter,
|
||||||
|
traffic_limiter.ServiceLimitKey,
|
||||||
|
limiter.ScopeOption(limiter.ScopeService),
|
||||||
|
limiter.ServiceOption(l.options.Service),
|
||||||
|
limiter.NetworkOption(conn.LocalAddr().Network()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
conn = metrics.WrapUDPConn(l.options.Service, conn)
|
||||||
|
if l.options.Stats != nil {
|
||||||
|
conn = stats.WrapUDPConn(conn, l.options.Stats)
|
||||||
|
}
|
||||||
|
conn = admission.WrapUDPConn(l.options.Admission, conn)
|
||||||
|
conn = limiter_wrapper.WrapUDPConn(
|
||||||
|
conn,
|
||||||
|
l.options.TrafficLimiter,
|
||||||
|
traffic_limiter.ServiceLimitKey,
|
||||||
|
limiter.ScopeOption(limiter.ScopeService),
|
||||||
|
limiter.ServiceOption(l.options.Service),
|
||||||
|
limiter.NetworkOption(conn.LocalAddr().Network()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = metrics.WrapPacketConn(l.options.Service, conn)
|
|
||||||
conn = stats.WrapPacketConn(conn, l.options.Stats)
|
|
||||||
conn = admission.WrapPacketConn(l.options.Admission, conn)
|
|
||||||
conn = limiter_wrapper.WrapPacketConn(
|
|
||||||
conn,
|
|
||||||
l.options.TrafficLimiter,
|
|
||||||
traffic_limiter.ServiceLimitKey,
|
|
||||||
limiter.ScopeOption(limiter.ScopeService),
|
|
||||||
limiter.ServiceOption(l.options.Service),
|
|
||||||
limiter.NetworkOption(conn.LocalAddr().Network()),
|
|
||||||
)
|
|
||||||
|
|
||||||
config := &quic.Config{
|
config := &quic.Config{
|
||||||
KeepAlivePeriod: l.md.keepAlivePeriod,
|
KeepAlivePeriod: l.md.keepAlivePeriod,
|
||||||
HandshakeIdleTimeout: l.md.handshakeTimeout,
|
HandshakeIdleTimeout: l.md.handshakeTimeout,
|
||||||
|
|||||||
Reference in new issue
Block a user