github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/mtu_discoverer_test.go (about) 1 package quic 2 3 import ( 4 "math/rand" 5 "time" 6 7 "github.com/metacubex/quic-go/internal/protocol" 8 "github.com/metacubex/quic-go/internal/utils" 9 "github.com/metacubex/quic-go/logging" 10 11 . "github.com/onsi/ginkgo/v2" 12 . "github.com/onsi/gomega" 13 ) 14 15 var _ = Describe("MTU Discoverer", func() { 16 const ( 17 rtt = 100 * time.Millisecond 18 startMTU protocol.ByteCount = 1000 19 maxMTU protocol.ByteCount = 2000 20 ) 21 22 var ( 23 d *mtuFinder 24 rttStats *utils.RTTStats 25 now time.Time 26 discoveredMTU protocol.ByteCount 27 ) 28 29 BeforeEach(func() { 30 rttStats = &utils.RTTStats{} 31 rttStats.SetInitialRTT(rtt) 32 Expect(rttStats.SmoothedRTT()).To(Equal(rtt)) 33 d = newMTUDiscoverer( 34 rttStats, 35 startMTU, 36 maxMTU, 37 func(s protocol.ByteCount) { discoveredMTU = s }, 38 nil, 39 ) 40 d.Start() 41 now = time.Now() 42 }) 43 44 It("only allows a probe 5 RTTs after the handshake completes", func() { 45 Expect(d.ShouldSendProbe(now)).To(BeFalse()) 46 Expect(d.ShouldSendProbe(now.Add(rtt * 9 / 2))).To(BeFalse()) 47 Expect(d.ShouldSendProbe(now.Add(rtt * 5))).To(BeTrue()) 48 }) 49 50 It("doesn't allow a probe if another probe is still in flight", func() { 51 ping, _ := d.GetPing() 52 Expect(d.ShouldSendProbe(now.Add(10 * rtt))).To(BeFalse()) 53 ping.Handler.OnLost(ping.Frame) 54 Expect(d.ShouldSendProbe(now.Add(10 * rtt))).To(BeTrue()) 55 }) 56 57 It("tries a lower size when a probe is lost", func() { 58 ping, size := d.GetPing() 59 Expect(size).To(Equal(protocol.ByteCount(1500))) 60 ping.Handler.OnLost(ping.Frame) 61 _, size = d.GetPing() 62 Expect(size).To(Equal(protocol.ByteCount(1250))) 63 }) 64 65 It("tries a higher size and calls the callback when a probe is acknowledged", func() { 66 ping, size := d.GetPing() 67 Expect(size).To(Equal(protocol.ByteCount(1500))) 68 ping.Handler.OnAcked(ping.Frame) 69 Expect(discoveredMTU).To(Equal(protocol.ByteCount(1500))) 70 _, size = d.GetPing() 71 Expect(size).To(Equal(protocol.ByteCount(1750))) 72 }) 73 74 It("stops discovery after getting close enough to the MTU", func() { 75 var sizes []protocol.ByteCount 76 t := now.Add(5 * rtt) 77 for d.ShouldSendProbe(t) { 78 ping, size := d.GetPing() 79 ping.Handler.OnAcked(ping.Frame) 80 sizes = append(sizes, size) 81 t = t.Add(5 * rtt) 82 } 83 Expect(sizes).To(Equal([]protocol.ByteCount{1500, 1750, 1875, 1937, 1968, 1984})) 84 Expect(d.ShouldSendProbe(t.Add(10 * rtt))).To(BeFalse()) 85 }) 86 87 It("doesn't do discovery before being started", func() { 88 d := newMTUDiscoverer(rttStats, startMTU, protocol.MaxByteCount, func(s protocol.ByteCount) {}, nil) 89 for i := 0; i < 5; i++ { 90 Expect(d.ShouldSendProbe(time.Now())).To(BeFalse()) 91 } 92 }) 93 94 It("finds the MTU", func() { 95 const rep = 3000 96 var maxDiff protocol.ByteCount 97 for i := 0; i < rep; i++ { 98 maxMTU := protocol.ByteCount(rand.Intn(int(3000-startMTU))) + startMTU + 1 99 currentMTU := startMTU 100 var tracedMTU protocol.ByteCount 101 var tracerDone bool 102 d := newMTUDiscoverer( 103 rttStats, 104 startMTU, 105 maxMTU, 106 func(s protocol.ByteCount) { currentMTU = s }, 107 &logging.ConnectionTracer{ 108 UpdatedMTU: func(mtu logging.ByteCount, done bool) { 109 tracedMTU = mtu 110 tracerDone = done 111 }, 112 }, 113 ) 114 d.Start() 115 now := time.Now() 116 realMTU := protocol.ByteCount(rand.Intn(int(maxMTU-startMTU))) + startMTU 117 t := now.Add(mtuProbeDelay * rtt) 118 var count int 119 for d.ShouldSendProbe(t) { 120 if count > 25 { 121 Fail("too many iterations") 122 } 123 count++ 124 125 ping, size := d.GetPing() 126 if size <= realMTU { 127 ping.Handler.OnAcked(ping.Frame) 128 } else { 129 ping.Handler.OnLost(ping.Frame) 130 } 131 t = t.Add(mtuProbeDelay * rtt) 132 } 133 diff := realMTU - currentMTU 134 Expect(diff).To(BeNumerically(">=", 0)) 135 maxDiff = utils.Max(maxDiff, diff) 136 if maxMTU > currentMTU+maxMTU { 137 Expect(tracedMTU).To(Equal(currentMTU)) 138 Expect(tracerDone).To(BeTrue()) 139 } 140 } 141 Expect(maxDiff).To(BeEquivalentTo(maxMTUDiff)) 142 }) 143 })