Add flow PortWithSelectorRange

This commit is contained in:
世界 2026-07-08 17:05:34 +08:00
parent 7c92d5e53e
commit 15b67423c3
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
2 changed files with 27 additions and 7 deletions

View file

@ -73,6 +73,11 @@ type Port interface {
WritePackets(packets [][]byte) error WritePackets(packets [][]byte) error
} }
type PortWithSelectorRange interface {
Port
PortSelectorRange() (start uint16, count uint16)
}
type Return interface { type Return interface {
ReturnHeadroom() int ReturnHeadroom() int
ReturnPackets(packets [][]byte) [][]byte ReturnPackets(packets [][]byte) [][]byte

View file

@ -19,6 +19,8 @@ type portNAT struct {
hasher maphash.Hasher[flowKey] hasher maphash.Hasher[flowKey]
shardMask uint32 shardMask uint32
shards []natShard shards []natShard
selectorStart uint16
selectorCount uint16
counter uint32 counter uint32
pending [][]byte pending [][]byte
@ -40,6 +42,9 @@ func newPortNAT(port Port) *portNAT {
shardMask: uint32(shardCount - 1), shardMask: uint32(shardCount - 1),
shards: make([]natShard, shardCount), shards: make([]natShard, shardCount),
} }
if rangedPort, isRanged := port.(PortWithSelectorRange); isRanged {
nat.selectorStart, nat.selectorCount = rangedPort.PortSelectorRange()
}
for i := range nat.shards { for i := range nat.shards {
nat.shards[i].flows = make(map[flowKey]*forwardFlow) nat.shards[i].flows = make(map[flowKey]*forwardFlow)
} }
@ -87,16 +92,26 @@ func (n *portNAT) reverseKeyFor(protocol uint8, portAddress, serverAddress netip
} }
} }
func (n *portNAT) selectorRange(protocol uint8) (uint16, uint32) {
if n.selectorCount == 0 ||
protocol == uint8(header.ICMPv4ProtocolNumber) || protocol == uint8(header.ICMPv6ProtocolNumber) {
return natSelectorMin, natSelectorMax - natSelectorMin + 1
}
return n.selectorStart, uint32(n.selectorCount)
}
func (n *portNAT) allocateSelector(protocol uint8, portAddress, serverAddress netip.Addr, serverPort, clientSelector uint16) (uint16, flowKey, bool) { func (n *portNAT) allocateSelector(protocol uint8, portAddress, serverAddress netip.Addr, serverPort, clientSelector uint16) (uint16, flowKey, bool) {
if clientSelector != 0 { rangeStart, rangeCount := n.selectorRange(protocol)
if clientSelector != 0 &&
clientSelector >= rangeStart && uint32(clientSelector-rangeStart) < rangeCount {
key := n.reverseKeyFor(protocol, portAddress, serverAddress, serverPort, clientSelector) key := n.reverseKeyFor(protocol, portAddress, serverAddress, serverPort, clientSelector)
if n.lookup(key) == nil { if n.lookup(key) == nil {
return clientSelector, key, true return clientSelector, key, true
} }
} }
for range natSelectorMax - natSelectorMin + 1 { for range rangeCount {
n.counter++ n.counter++
candidate := uint16(natSelectorMin + n.counter%(natSelectorMax-natSelectorMin+1)) candidate := rangeStart + uint16(n.counter%rangeCount)
key := n.reverseKeyFor(protocol, portAddress, serverAddress, serverPort, candidate) key := n.reverseKeyFor(protocol, portAddress, serverAddress, serverPort, candidate)
if n.lookup(key) == nil { if n.lookup(key) == nil {
return candidate, key, true return candidate, key, true