forked from quic-go/quic-go
disable GSO if sending fails for a particular remote address
This commit is contained in:
@@ -2,46 +2,81 @@ package quic
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/utils"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
// Only if appendUDPSegmentSizeMsg actually appends a message (and isn't only a stub implementation),
|
||||
// GSO is actually supported on this platform.
|
||||
var platformSupportsGSO = len(appendUDPSegmentSizeMsg([]byte{}, 1337)) > 0
|
||||
|
||||
var _ = Describe("Connection (for sending packets)", func() {
|
||||
var (
|
||||
c sendConn
|
||||
packetConn *MockPacketConn
|
||||
addr net.Addr
|
||||
)
|
||||
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
|
||||
|
||||
BeforeEach(func() {
|
||||
addr = &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
|
||||
packetConn = NewMockPacketConn(mockCtrl)
|
||||
rawConn, err := wrapConn(packetConn)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
c = newSendConnWithPacketInfo(rawConn, addr, packetInfo{})
|
||||
})
|
||||
|
||||
It("writes", func() {
|
||||
packetConn.EXPECT().WriteTo([]byte("foobar"), addr)
|
||||
Expect(c.Write([]byte("foobar"), 6)).To(Succeed())
|
||||
})
|
||||
|
||||
It("gets the remote address", func() {
|
||||
It("gets the local and remote addresses", func() {
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1234}
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr().Return(localAddr)
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
|
||||
Expect(c.LocalAddr().String()).To(Equal("192.168.0.1:1234"))
|
||||
Expect(c.RemoteAddr().String()).To(Equal("192.168.100.200:1337"))
|
||||
})
|
||||
|
||||
It("gets the local address", func() {
|
||||
addr := &net.UDPAddr{
|
||||
IP: net.IPv4(192, 168, 0, 1),
|
||||
Port: 1234,
|
||||
}
|
||||
packetConn.EXPECT().LocalAddr().Return(addr)
|
||||
Expect(c.LocalAddr()).To(Equal(addr))
|
||||
It("uses the local address from the packet info", func() {
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1234}
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr().Return(localAddr)
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{addr: netip.AddrFrom4([4]byte{127, 0, 0, 42})}, utils.DefaultLogger)
|
||||
Expect(c.LocalAddr().String()).To(Equal("127.0.0.42:1234"))
|
||||
})
|
||||
|
||||
It("closes", func() {
|
||||
packetConn.EXPECT().Close()
|
||||
Expect(c.Close()).To(Succeed())
|
||||
})
|
||||
if platformSupportsGSO {
|
||||
It("writes with GSO", func() {
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr()
|
||||
rawConn.EXPECT().capabilities().Return(connCapabilities{GSO: true}).AnyTimes()
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
|
||||
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any()).Do(func(_ []byte, _ net.Addr, oob []byte) {
|
||||
msg := appendUDPSegmentSizeMsg([]byte{}, 3)
|
||||
Expect(oob).To(Equal(msg))
|
||||
})
|
||||
Expect(c.Write([]byte("foobar"), 3)).To(Succeed())
|
||||
})
|
||||
|
||||
It("disables GSO if writing fails", func() {
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr()
|
||||
rawConn.EXPECT().capabilities().Return(connCapabilities{GSO: true}).AnyTimes()
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
|
||||
Expect(c.capabilities().GSO).To(BeTrue())
|
||||
gomock.InOrder(
|
||||
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any()).DoAndReturn(func(_ []byte, _ net.Addr, oob []byte) (int, error) {
|
||||
msg := appendUDPSegmentSizeMsg([]byte{}, 3)
|
||||
Expect(oob).To(Equal(msg))
|
||||
return 0, errGSO
|
||||
}),
|
||||
rawConn.EXPECT().WritePacket([]byte("foo"), remoteAddr, []byte{}).Return(3, nil),
|
||||
rawConn.EXPECT().WritePacket([]byte("bar"), remoteAddr, []byte{}).Return(3, nil),
|
||||
)
|
||||
Expect(c.Write([]byte("foobar"), 3)).To(Succeed())
|
||||
Expect(c.capabilities().GSO).To(BeFalse()) // GSO support is now disabled
|
||||
// make sure we actually enforce that
|
||||
Expect(func() { c.Write([]byte("foobar"), 3) }).To(PanicWith("inconsistent packet size (6 vs 3)"))
|
||||
})
|
||||
} else {
|
||||
It("writes without GSO", func() {
|
||||
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr()
|
||||
rawConn.EXPECT().capabilities()
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
|
||||
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, nil)
|
||||
Expect(c.Write([]byte("foobar"), 6)).To(Succeed())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user