mirror of
https://github.com/slackhq/nebula.git
synced 2026-08-16 10:36:59 +02:00
overlay/batch: ship never-grown slots as plain writes
A slot that stays single-segment is byte-identical to the packet it was seeded from, but flushSlot re-emitted it via WriteGSO with a seeded pseudo-sum, forcing the kernel to software-checksum up to ~1400B that arrived with a perfectly valid checksum. Keep the borrowed seed packet on the slot (valid until Flush per the Commit contract) and emit it through the plain DATA_VALID path when numSeg is still 1 at flush time. appendPayload and mergeSlots only touch hdrBuf once numSeg >= 2, so the raw bytes are pristine whenever the fast path fires. This is every non-coalesced TCP/UDP packet: request/response flows, many-flow fan-in, and each run's leftover tail. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ugV2edVqoz3tBvq9J6yWp
This commit is contained in:
@@ -37,7 +37,11 @@ const tcpCoalesceHdrCap = 100
|
||||
// The caller (listenOut) must keep those buffers alive until Flush.
|
||||
type coalesceSlot struct {
|
||||
passthrough bool
|
||||
rawPkt []byte // borrowed when passthrough
|
||||
// rawPkt is borrowed: the whole packet for passthrough slots, the seed
|
||||
// packet for coalesce slots. A coalesce slot that never grows past one
|
||||
// segment is emitted from rawPkt so its original (already valid) L4
|
||||
// checksum ships DATA_VALID instead of making the kernel recompute it.
|
||||
rawPkt []byte
|
||||
|
||||
fk flowKey
|
||||
hdrBuf [tcpCoalesceHdrCap]byte
|
||||
@@ -235,7 +239,12 @@ func (c *TCPCoalescer) Flush() error {
|
||||
var first error
|
||||
for _, s := range c.slots {
|
||||
var err error
|
||||
if s.passthrough {
|
||||
if s.passthrough || s.numSeg == 1 {
|
||||
// A slot that never grew (nor absorbed a merge) is byte-identical
|
||||
// to the packet it was seeded from; ship the original so its valid
|
||||
// checksum rides the DATA_VALID path instead of paying a kernel
|
||||
// software csum. appendPayload and mergeSlots only touch hdrBuf
|
||||
// once numSeg >= 2, so rawPkt is still pristine here.
|
||||
_, err = c.w.Write(s.rawPkt)
|
||||
} else {
|
||||
err = c.flushSlot(s)
|
||||
@@ -268,7 +277,7 @@ func (c *TCPCoalescer) seed(pkt []byte, info parsedTCP) {
|
||||
}
|
||||
s := c.take()
|
||||
s.passthrough = false
|
||||
s.rawPkt = nil
|
||||
s.rawPkt = pkt // kept for the numSeg==1 fast path in Flush
|
||||
copy(s.hdrBuf[:], pkt[:info.hdrLen])
|
||||
s.hdrLen = info.hdrLen
|
||||
s.ipHdrLen = info.ipHdrLen
|
||||
|
||||
Reference in New Issue
Block a user