JackDoan 5 ヶ月 前
親
コミット
1c601d776a
2 ファイル変更、38 行追加、0 行削除
  1. 5 0
      overlay/batch/tcp_coalesce.go
  2. 33 0
      overlay/batch/tcp_coalesce_test.go

+ 5 - 0
overlay/batch/tcp_coalesce.go

@@ -344,6 +344,11 @@ func (c *TCPCoalescer) appendPayload(s *coalesceSlot, pkt []byte, info parsedTCP
 	s.numSeg++
 	s.totalPay += info.payLen
 	s.nextSeq = info.seq + uint32(info.payLen)
+	if info.flags&0x08 != 0 {
+		// Propagate PSH into the seed header so kernel TSO sets it on the
+		// last segment. Without this the sender's push signal is dropped.
+		s.hdrBuf[s.ipHdrLen+13] |= 0x08
+	}
 	if info.payLen < s.gsoSize || info.flags&0x08 != 0 {
 		s.psh = true
 	}

+ 33 - 0
overlay/batch/tcp_coalesce_test.go

@@ -343,6 +343,39 @@ func TestCoalescerPSHFinalizesChain(t *testing.T) {
 	}
 }
 
+// TestCoalescerPropagatesPSHFromAppended ensures that when an appended
+// segment carries PSH (or is short, sealing the chain), the PSH bit ends
+// up in the emitted superpacket's TCP flags. The kernel TSO path keeps
+// PSH only on the last segment iff the input header has it set; if the
+// coalescer drops it the sender's push signal never reaches the receiver.
+func TestCoalescerPropagatesPSHFromAppended(t *testing.T) {
+	w := &fakeTunWriter{gsoEnabled: true}
+	c := NewTCPCoalescer(w)
+	pay := make([]byte, 1200)
+	// Seed has no PSH; second segment carries PSH and seals the chain.
+	if err := c.Commit(buildTCPv4(1000, tcpAck, pay)); err != nil {
+		t.Fatal(err)
+	}
+	if err := c.Commit(buildTCPv4(2200, tcpAckPsh, pay)); err != nil {
+		t.Fatal(err)
+	}
+	if err := c.Flush(0); err != nil {
+		t.Fatal(err)
+	}
+	if len(w.gsoWrites) != 1 {
+		t.Fatalf("want 1 gso write got %d", len(w.gsoWrites))
+	}
+	g := w.gsoWrites[0]
+	const ipHdrLen = 20
+	flags := g.hdr[ipHdrLen+13]
+	if flags&tcpPsh == 0 {
+		t.Fatalf("PSH lost from coalesced superpacket: flags=0x%02x", flags)
+	}
+	if flags&tcpAck == 0 {
+		t.Fatalf("ACK missing from coalesced superpacket: flags=0x%02x", flags)
+	}
+}
+
 func TestCoalescerRejectsDifferentFlow(t *testing.T) {
 	w := &fakeTunWriter{gsoEnabled: true}
 	c := NewTCPCoalescer(w)