From 523f60976184f24a2fc1f8d09d2c5eb03aae073c Mon Sep 17 00:00:00 2001 From: soypat Date: Sun, 16 Feb 2025 14:47:02 -0300 Subject: [PATCH] now supports partial packet acks --- tcp/txqueue.go | 6 +++--- tcp/txqueue_test.go | 30 ++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/tcp/txqueue.go b/tcp/txqueue.go index 33898e2..1bfe450 100644 --- a/tcp/txqueue.go +++ b/tcp/txqueue.go @@ -192,7 +192,7 @@ func (rtx *ringTx) RecvACK(ack Value) error { acked := int(ack - pkt.seq) pring := rtx.ring(pkt.off, pkt.end) buffered := pring.Buffered() - if acked > buffered || acked <= minBufferSize { + if acked > buffered || acked < minBufferSize { panic("unreachable") } off := rtx.addOff(pkt.off, acked) @@ -266,7 +266,7 @@ func (rtx *ringTx) firstPkt() int { idx := -1 for i := 0; i < len(rtx.packets); i++ { pkt := &rtx.packets[i] - if pkt.sent() && (idx == -1 || seq.LessThan(pkt.seq)) { + if pkt.sent() && (idx == -1 || pkt.seq.LessThan(seq)) { seq = pkt.seq idx = i } @@ -279,7 +279,7 @@ func (rtx *ringTx) lastPkt() int { idx := -1 for i := 0; i < len(rtx.packets); i++ { pkt := &rtx.packets[i] - if pkt.sent() && (idx == -1 || pkt.seq.LessThan(seq)) { + if pkt.sent() && (idx == -1 || seq.LessThan(pkt.seq)) { seq = pkt.seq idx = i } diff --git a/tcp/txqueue_test.go b/tcp/txqueue_test.go index e3488c3..0d0e6b7 100644 --- a/tcp/txqueue_test.go +++ b/tcp/txqueue_test.go @@ -12,9 +12,12 @@ func TestTxQueue(t *testing.T) { const bufsize = 1024 var msgBuf, ringBuf, readBuf, aux [bufsize]byte rng := rand.New(rand.NewSource(1)) - + panicked := true var rtx ringTx defer func() { + if panicked { + t.Error("panicked, rtx:\n", rtx.string()) + } testQueueSanity(t, &rtx) }() increasingComplexityTests := []struct { @@ -92,7 +95,7 @@ func TestTxQueue(t *testing.T) { }, }, 2: { - name: "ParialAcks", + name: "PartialAcks", test: func(t *testing.T) { const startAck = 0 const packets = 100 @@ -153,6 +156,7 @@ func TestTxQueue(t *testing.T) { t.Fatalf("subtest %d/%d %q failed, not running more complex tests until fixed", i+1, len(increasingComplexityTests), test.name) } } + panicked = false } func testQueueSanity(t *testing.T, rtx *ringTx) { @@ -213,6 +217,28 @@ func testQueueSanity(t *testing.T, rtx *ringTx) { } else if !allEmpty && sentEmpty && unsentEmpty { t.Fatal("all buffer not empty but sent&unsentempty") } + + // Check sanenness of last/first packets. + last := rtx.lastPkt() + first := rtx.firstPkt() + if first < 0 && last >= 0 || last < 0 && first >= 0 { + t.Fatalf("found first/last(%d,%d) but did not find last/first", first, last) + } + // Check sent data or return if no sent data available. + if sent == 0 { + return + } + lastPkt := rtx.pkt(last) + endseq, ok := rtx.endSeq() + firstPkt := rtx.pkt(first) + lastEndSeq := Add(lastPkt.seq, lastPkt.size) + if lastPkt.seq.LessThan(firstPkt.seq) { + t.Fatalf("first packet not previous to last packet seq, wanted %d<%d", firstPkt.seq, lastPkt.seq) + } else if !ok { + t.Fatal("unexpected end sequence not found") + } else if lastEndSeq != endseq { + t.Fatalf("last packet end sequence not match with got endSeq %d!=%d", lastEndSeq, endseq) + } } func (rx *ringTx) string() string {