diff --git a/network/clean.go b/network/clean.go index d4fb50f3..b15fbaa0 100644 --- a/network/clean.go +++ b/network/clean.go @@ -48,6 +48,7 @@ func cleanConnections() (activePIDs map[int]struct{}) { _ = module.RunMicroTask("clean connections", 0, func(ctx context.Context) error { now := time.Now().UTC() nowUnix := now.Unix() + ignoreNewer := nowUnix - 1 deleteOlderThan := now.Add(-DeleteConnsAfterEndedThreshold).Unix() deleteIncompleteOlderThan := now.Add(-DeleteIncompleteConnsAfterStartedThreshold).Unix() @@ -57,6 +58,8 @@ func cleanConnections() (activePIDs map[int]struct{}) { // delete inactive connections switch { + case conn.Started >= ignoreNewer: + // Skip very fresh connections to evade edge cases. case !conn.DataIsComplete(): // Step 0: delete old incomplete connections if conn.Started < deleteIncompleteOlderThan { @@ -76,6 +79,7 @@ func cleanConnections() (activePIDs map[int]struct{}) { Dst: conn.Entity.IP, DstPort: conn.Entity.Port, PID: process.UndefinedProcessID, + SeenAt: time.Unix(conn.Started, 0), // State tables will be updated if older than this. }, now) // Step 2: mark as ended diff --git a/network/state/exists.go b/network/state/exists.go index 967b8f95..89a0fff9 100644 --- a/network/state/exists.go +++ b/network/state/exists.go @@ -35,6 +35,11 @@ func Exists(pktInfo *packet.Info, now time.Time) (exists bool) { } func (table *tcpTable) exists(pktInfo *packet.Info) (exists bool) { + // Update tables if older than the connection that is checked. + if table.lastUpdateAt.Load() < pktInfo.SeenAt.UnixNano() { + table.updateTables(table.updateIter.Load()) + } + table.lock.RLock() defer table.lock.RUnlock() @@ -57,6 +62,11 @@ func (table *tcpTable) exists(pktInfo *packet.Info) (exists bool) { } func (table *udpTable) exists(pktInfo *packet.Info, now time.Time) (exists bool) { + // Update tables if older than the connection that is checked. + if table.lastUpdateAt.Load() < pktInfo.SeenAt.UnixNano() { + table.updateTables(table.updateIter.Load()) + } + table.lock.RLock() defer table.lock.RUnlock() diff --git a/network/state/lookup.go b/network/state/lookup.go index 2aad2d73..eea7ec37 100644 --- a/network/state/lookup.go +++ b/network/state/lookup.go @@ -76,7 +76,7 @@ func (table *tcpTable) lookup(pktInfo *packet.Info, fast bool) ( // Search for the socket until found. for i := 1; i <= lookupTries; i++ { // Get or update tables. - if i == 1 { + if i == 1 && pktInfo.SeenAt.UnixNano() >= table.lastUpdateAt.Load() { connections, listeners, updateIter = table.getCurrentTables() } else { connections, listeners, updateIter = table.updateTables(updateIter) @@ -179,7 +179,7 @@ func (table *udpTable) lookup(pktInfo *packet.Info, fast bool) ( // Search for the socket until found. for i := 1; i <= lookupTries; i++ { // Get or update tables. - if i == 1 { + if i == 1 && pktInfo.SeenAt.UnixNano() >= table.lastUpdateAt.Load() { binds, updateIter = table.getCurrentTables() } else { binds, updateIter = table.updateTables(updateIter) diff --git a/network/state/tcp.go b/network/state/tcp.go index 4b423a21..35aa9ef9 100644 --- a/network/state/tcp.go +++ b/network/state/tcp.go @@ -17,9 +17,12 @@ type tcpTable struct { connections []*socket.ConnectionInfo listeners []*socket.BindInfo - updateIter atomic.Uint64 lock sync.RWMutex + updateIter atomic.Uint64 + // lastUpdateAt stores the time when the tables where last updated as unix nanoseconds. + lastUpdateAt atomic.Int64 + fetchingLock sync.Mutex fetchingInProgress bool fetchingDoneSignal chan struct{} @@ -133,6 +136,7 @@ func (table *tcpTable) updateTables(previousUpdateIter uint64) ( table.connections = connections table.listeners = listeners table.updateIter.Add(1) + table.lastUpdateAt.Store(time.Now().UnixNano()) // Return new tables immediately. return table.connections, table.listeners, table.updateIter.Load() diff --git a/network/state/udp.go b/network/state/udp.go index 1823a371..cdfd604e 100644 --- a/network/state/udp.go +++ b/network/state/udp.go @@ -17,9 +17,12 @@ import ( type udpTable struct { version int - binds []*socket.BindInfo + binds []*socket.BindInfo + lock sync.RWMutex + updateIter atomic.Uint64 - lock sync.RWMutex + // lastUpdateAt stores the time when the tables where last updated as unix nanoseconds. + lastUpdateAt atomic.Int64 fetchingLock sync.Mutex fetchingInProgress bool @@ -152,6 +155,7 @@ func (table *udpTable) updateTables(previousUpdateIter uint64) ( defer table.lock.Unlock() table.binds = binds table.updateIter.Add(1) + table.lastUpdateAt.Store(time.Now().UnixNano()) // Return new tables immediately. return table.binds, table.updateIter.Load()