Reduce VPN control packet latency

This commit is contained in:
2026-05-15 18:19:55 +03:00
parent ceda460d09
commit 52dfce316d
7 changed files with 194 additions and 15 deletions
@@ -1794,17 +1794,22 @@ func (t *FabricPacketTransport) ReceiveGatewayPacketBatch(ctx context.Context, t
type FabricPacketInbox struct {
capacity int
mu sync.Mutex
queues map[string]chan mesh.VPNPacketBatchPayload
queues map[string]*fabricPacketInboxQueue
dropped uint64
}
type fabricPacketInboxQueue struct {
normal chan mesh.VPNPacketBatchPayload
priority chan mesh.VPNPacketBatchPayload
}
func NewFabricPacketInbox(capacity int) *FabricPacketInbox {
if capacity <= 0 {
capacity = 4096
}
return &FabricPacketInbox{
capacity: capacity,
queues: map[string]chan mesh.VPNPacketBatchPayload{},
queues: map[string]*fabricPacketInboxQueue{},
}
}
@@ -1860,12 +1865,46 @@ func (i *FabricPacketInbox) Receive(ctx context.Context, vpnConnectionID, direct
defer timer.Stop()
queue := i.queue(vpnConnectionID, direction)
for {
select {
case payload := <-queue.priority:
packets := cleanPacketBatch(payload.Packets)
if len(packets) == 0 {
continue
}
return packets, nil
default:
}
if len(queue.normal) > 0 {
priorityTimer := time.NewTimer(2 * time.Millisecond)
select {
case <-ctx.Done():
priorityTimer.Stop()
return nil, ctx.Err()
case <-timer.C:
priorityTimer.Stop()
return nil, nil
case payload := <-queue.priority:
priorityTimer.Stop()
packets := cleanPacketBatch(payload.Packets)
if len(packets) == 0 {
continue
}
return packets, nil
case <-priorityTimer.C:
}
}
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-timer.C:
return nil, nil
case payload := <-queue:
case payload := <-queue.priority:
packets := cleanPacketBatch(payload.Packets)
if len(packets) == 0 {
continue
}
return packets, nil
case payload := <-queue.normal:
packets := cleanPacketBatch(payload.Packets)
if len(packets) == 0 {
continue
@@ -1877,8 +1916,12 @@ func (i *FabricPacketInbox) Receive(ctx context.Context, vpnConnectionID, direct
func (i *FabricPacketInbox) enqueue(payload mesh.VPNPacketBatchPayload) error {
queue := i.queue(payload.VPNConnectionID, payload.Direction)
target := queue.normal
if payload.Direction == FabricDirectionGatewayToClient && batchHasTCPControlPacket(payload.Packets) {
target = queue.priority
}
select {
case queue <- payload:
case target <- payload:
default:
i.mu.Lock()
i.dropped++
@@ -1887,21 +1930,41 @@ func (i *FabricPacketInbox) enqueue(payload mesh.VPNPacketBatchPayload) error {
return nil
}
func (i *FabricPacketInbox) queue(vpnConnectionID, direction string) chan mesh.VPNPacketBatchPayload {
func (i *FabricPacketInbox) queue(vpnConnectionID, direction string) *fabricPacketInboxQueue {
key := vpnConnectionID + "\x00" + direction
i.mu.Lock()
defer i.mu.Unlock()
if i.queues == nil {
i.queues = map[string]chan mesh.VPNPacketBatchPayload{}
i.queues = map[string]*fabricPacketInboxQueue{}
}
queue, ok := i.queues[key]
if !ok {
queue = make(chan mesh.VPNPacketBatchPayload, i.capacity)
priorityCapacity := maxInt(1, i.capacity/4)
queue = &fabricPacketInboxQueue{
normal: make(chan mesh.VPNPacketBatchPayload, i.capacity),
priority: make(chan mesh.VPNPacketBatchPayload, priorityCapacity),
}
i.queues[key] = queue
}
return queue
}
func batchHasTCPControlPacket(packets [][]byte) bool {
for _, packet := range packets {
if isTCPControlPacket(packet) {
return true
}
}
return false
}
func maxInt(a, b int) int {
if a > b {
return a
}
return b
}
func (i *FabricPacketInbox) Dropped() uint64 {
if i == nil {
return 0
@@ -1933,7 +1996,7 @@ func (i *FabricPacketInbox) Snapshot() FabricPacketInboxSnapshot {
snapshot.Dropped = i.dropped
snapshot.QueueCount = len(i.queues)
for key, queue := range i.queues {
snapshot.QueueDepths[strings.ReplaceAll(key, "\x00", ":")] = len(queue)
snapshot.QueueDepths[strings.ReplaceAll(key, "\x00", ":")] = len(queue.normal) + len(queue.priority)
}
return snapshot
}