Fix flow close reasons
This commit is contained in:
parent
2de01a4c29
commit
dcfbe83ca6
3 changed files with 29 additions and 24 deletions
13
flow.go
13
flow.go
|
|
@ -41,27 +41,16 @@ const (
|
||||||
FlowCloseReset FlowCloseReason = iota
|
FlowCloseReset FlowCloseReason = iota
|
||||||
FlowCloseFinished
|
FlowCloseFinished
|
||||||
FlowCloseTimeout
|
FlowCloseTimeout
|
||||||
FlowCloseEvicted
|
|
||||||
FlowCloseShutdown
|
|
||||||
FlowCloseInterrupted
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r FlowCloseReason) String() string {
|
func (r FlowCloseReason) String() string {
|
||||||
switch r {
|
switch r {
|
||||||
case FlowCloseReset:
|
|
||||||
return "connection reset"
|
|
||||||
case FlowCloseFinished:
|
case FlowCloseFinished:
|
||||||
return "finished"
|
return "finished"
|
||||||
case FlowCloseTimeout:
|
case FlowCloseTimeout:
|
||||||
return "idle timeout"
|
return "idle timeout"
|
||||||
case FlowCloseEvicted:
|
|
||||||
return "evicted"
|
|
||||||
case FlowCloseShutdown:
|
|
||||||
return "stack closed"
|
|
||||||
case FlowCloseInterrupted:
|
|
||||||
return "interrupted"
|
|
||||||
default:
|
default:
|
||||||
return "unknown"
|
return "connection reset"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,15 +59,16 @@ type forwardFlow struct {
|
||||||
dnatAddress bool
|
dnatAddress bool
|
||||||
dnatPort bool
|
dnatPort bool
|
||||||
|
|
||||||
finForward bool
|
finForward atomic.Bool
|
||||||
established atomic.Bool
|
established atomic.Bool
|
||||||
finReverse atomic.Bool
|
finReverse atomic.Bool
|
||||||
|
reported atomic.Bool
|
||||||
closed atomic.Bool
|
closed atomic.Bool
|
||||||
lastReverse atomic.Int64
|
lastReverse atomic.Int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *forwardFlow) close(reason FlowCloseReason) {
|
func (f *forwardFlow) report(reason FlowCloseReason) {
|
||||||
if !f.closed.CompareAndSwap(false, true) {
|
if !f.reported.CompareAndSwap(false, true) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if f.tracker != nil {
|
if f.tracker != nil {
|
||||||
|
|
@ -75,8 +76,15 @@ func (f *forwardFlow) close(reason FlowCloseReason) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *forwardFlow) close(reason FlowCloseReason) {
|
||||||
|
if !f.closed.CompareAndSwap(false, true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.report(reason)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *forwardFlow) CloseFlow() {
|
func (f *forwardFlow) CloseFlow() {
|
||||||
f.close(FlowCloseInterrupted)
|
f.close(FlowCloseReset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *forwardFlow) observeReverse(packet *forwardPacket, now int64) {
|
func (f *forwardFlow) observeReverse(packet *forwardPacket, now int64) {
|
||||||
|
|
@ -93,6 +101,8 @@ func (f *forwardFlow) observeReverse(packet *forwardPacket, now int64) {
|
||||||
}
|
}
|
||||||
if packet.tcpFlags&header.TCPFlagFin != 0 {
|
if packet.tcpFlags&header.TCPFlagFin != 0 {
|
||||||
f.finReverse.Store(true)
|
f.finReverse.Store(true)
|
||||||
|
} else if f.finReverse.Load() && f.finForward.Load() {
|
||||||
|
f.report(FlowCloseFinished)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +169,7 @@ func (d *ForwardDispatcher) Close() {
|
||||||
d.returnPath.closed.Store(true)
|
d.returnPath.closed.Store(true)
|
||||||
for _, entry := range d.table {
|
for _, entry := range d.table {
|
||||||
if entry.flow != nil {
|
if entry.flow != nil {
|
||||||
entry.flow.close(FlowCloseShutdown)
|
entry.flow.close(FlowCloseReset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for port, nat := range d.ports {
|
for port, nat := range d.ports {
|
||||||
|
|
@ -202,6 +212,7 @@ func (d *ForwardDispatcher) handleHit(key flowKey, entry *flowEntry, packet *for
|
||||||
d.tombstoneEntry(entry, now)
|
d.tombstoneEntry(entry, now)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
var flowFinished bool
|
||||||
if packet.protocol == uint8(header.TCPProtocolNumber) {
|
if packet.protocol == uint8(header.TCPProtocolNumber) {
|
||||||
if packet.tcpFlags&header.TCPFlagRst != 0 {
|
if packet.tcpFlags&header.TCPFlagRst != 0 {
|
||||||
d.forwardToPort(flow, packet, raw)
|
d.forwardToPort(flow, packet, raw)
|
||||||
|
|
@ -210,12 +221,17 @@ func (d *ForwardDispatcher) handleHit(key flowKey, entry *flowEntry, packet *for
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if packet.tcpFlags&header.TCPFlagFin != 0 {
|
if packet.tcpFlags&header.TCPFlagFin != 0 {
|
||||||
flow.finForward = true
|
flow.finForward.Store(true)
|
||||||
|
} else if flow.finForward.Load() && flow.finReverse.Load() {
|
||||||
|
flowFinished = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry.idle = d.flowIdle(flow)
|
entry.idle = d.flowIdle(flow)
|
||||||
entry.deadline = now + int64(entry.idle)
|
entry.deadline = now + int64(entry.idle)
|
||||||
d.forwardToPort(flow, packet, raw)
|
d.forwardToPort(flow, packet, raw)
|
||||||
|
if flowFinished {
|
||||||
|
flow.report(FlowCloseFinished)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
case ActionAccept:
|
case ActionAccept:
|
||||||
if packet.protocol == uint8(header.TCPProtocolNumber) {
|
if packet.protocol == uint8(header.TCPProtocolNumber) {
|
||||||
|
|
@ -302,13 +318,13 @@ func (d *ForwardDispatcher) idleTimeout(protocol uint8, established bool) time.D
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ForwardDispatcher) flowIdle(flow *forwardFlow) time.Duration {
|
func (d *ForwardDispatcher) flowIdle(flow *forwardFlow) time.Duration {
|
||||||
if flow.protocol == uint8(header.TCPProtocolNumber) && flow.finForward && flow.finReverse.Load() {
|
if flow.protocol == uint8(header.TCPProtocolNumber) && flow.finForward.Load() && flow.finReverse.Load() {
|
||||||
return tcpClosingTimeout
|
return tcpClosingTimeout
|
||||||
}
|
}
|
||||||
if flow.udpTimeout > 0 {
|
if flow.udpTimeout > 0 {
|
||||||
return flow.udpTimeout
|
return flow.udpTimeout
|
||||||
}
|
}
|
||||||
established := flow.established.Load() && !flow.finForward && !flow.finReverse.Load()
|
established := flow.established.Load() && !flow.finForward.Load() && !flow.finReverse.Load()
|
||||||
return d.idleTimeout(flow.protocol, established)
|
return d.idleTimeout(flow.protocol, established)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -569,7 +585,7 @@ func (d *ForwardDispatcher) tombstoneEntry(entry *flowEntry, now int64) {
|
||||||
func (d *ForwardDispatcher) removeEntry(key flowKey, entry *flowEntry, reason FlowCloseReason) {
|
func (d *ForwardDispatcher) removeEntry(key flowKey, entry *flowEntry, reason FlowCloseReason) {
|
||||||
delete(d.table, key)
|
delete(d.table, key)
|
||||||
if entry.flow != nil {
|
if entry.flow != nil {
|
||||||
if reason == FlowCloseTimeout && entry.flow.finForward && entry.flow.finReverse.Load() {
|
if reason == FlowCloseTimeout && entry.flow.finForward.Load() && entry.flow.finReverse.Load() {
|
||||||
reason = FlowCloseFinished
|
reason = FlowCloseFinished
|
||||||
}
|
}
|
||||||
entry.flow.close(reason)
|
entry.flow.close(reason)
|
||||||
|
|
@ -605,7 +621,7 @@ func (d *ForwardDispatcher) evictEntries(now int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if freed == 0 && oldest != nil {
|
if freed == 0 && oldest != nil {
|
||||||
d.removeEntry(oldestKey, oldest, FlowCloseEvicted)
|
d.removeEntry(oldestKey, oldest, FlowCloseReset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ func (f *icmpFlow) close(reason FlowCloseReason) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *icmpFlow) CloseFlow() {
|
func (f *icmpFlow) CloseFlow() {
|
||||||
f.close(FlowCloseInterrupted)
|
f.close(FlowCloseReset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewICMPForwarder(stack *stack.Stack, handler Handler, logger logger.Logger) *ICMPForwarder {
|
func NewICMPForwarder(stack *stack.Stack, handler Handler, logger logger.Logger) *ICMPForwarder {
|
||||||
|
|
@ -77,7 +77,7 @@ func (f *ICMPForwarder) Close() error {
|
||||||
f.flowAccess.Lock()
|
f.flowAccess.Lock()
|
||||||
defer f.flowAccess.Unlock()
|
defer f.flowAccess.Unlock()
|
||||||
for key, flow := range f.flows {
|
for key, flow := range f.flows {
|
||||||
flow.close(FlowCloseShutdown)
|
flow.close(FlowCloseReset)
|
||||||
delete(f.flows, key)
|
delete(f.flows, key)
|
||||||
}
|
}
|
||||||
for port := range f.attachedPorts {
|
for port := range f.attachedPorts {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue