mirror of
https://github.com/slackhq/nebula.git
synced 2026-08-16 15:27:01 +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:
@@ -25,7 +25,11 @@ const udpCoalesceHdrCap = 64
|
||||
// udpSlot is one entry in the UDPCoalescer's ordered event queue.
|
||||
type udpSlot 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 [udpCoalesceHdrCap]byte
|
||||
@@ -170,7 +174,10 @@ func (c *UDPCoalescer) 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 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.
|
||||
_, err = c.w.Write(s.rawPkt)
|
||||
} else {
|
||||
err = c.flushSlot(s)
|
||||
@@ -201,7 +208,7 @@ func (c *UDPCoalescer) seed(pkt []byte, info parsedUDP) {
|
||||
}
|
||||
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