Skip to content

Commit

Permalink
inbound-governor: verify inbound governor state invariant
Browse files Browse the repository at this point in the history
  • Loading branch information
coot committed May 6, 2024
1 parent 18e92c9 commit 1a0f009
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 15 deletions.
1 change: 1 addition & 0 deletions ouroboros-network-framework/demo/connection-manager.hs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ withBidirectionalConnectionManager snocket makeBearer socket
serverTracer = ("server",) `contramap` debugTracer, -- ServerTrace
serverTrTracer = nullTracer,
serverInboundGovernorTracer = ("inbound-governor",) `contramap` debugTracer,
serverDebugInboundGovernor = nullTracer,
serverConnectionLimits = AcceptedConnectionsLimit maxBound maxBound 0,
serverConnectionManager = connectionManager,
serverInboundIdleTimeout = Just protocolIdleTimeout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ test-suite sim-tests
, iproute
, network
, pretty-simple
, psqueues
, random
, serialise
, text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
Expand Down Expand Up @@ -52,6 +53,7 @@ import Data.Map.Strict qualified as Map
import Data.Maybe (fromMaybe)
import Data.Monoid (Sum (..))
import Data.Monoid.Synchronisation (FirstToFinish (..))
import Data.OrdPSQ qualified as OrdPSQ
import Data.Set qualified as Set
import Data.Typeable (Typeable)
import System.Random (StdGen, mkStdGen, split)
Expand All @@ -70,9 +72,11 @@ import Ouroboros.Network.ConnectionHandler
import Ouroboros.Network.ConnectionId
import Ouroboros.Network.ConnectionManager.Types
import Ouroboros.Network.ConnectionManager.Types qualified as CM
import Ouroboros.Network.InboundGovernor (InboundGovernorTrace (..))
import Ouroboros.Network.InboundGovernor (DebugInboundGovernor (..),
InboundGovernorTrace (..))
import Ouroboros.Network.InboundGovernor qualified as IG
import Ouroboros.Network.InboundGovernor.State (InboundGovernorCounters (..))
import Ouroboros.Network.InboundGovernor.State (ConnectionState (..),
InboundGovernorCounters (..))
import Ouroboros.Network.Mux
import Ouroboros.Network.MuxMode
import Ouroboros.Network.Protocol.Handshake.Codec (noTimeLimitsHandshake,
Expand All @@ -98,6 +102,7 @@ import Ouroboros.Network.ConnectionManager.Test.Utils
(abstractStateIsFinalTransition, allValidTransitionsNames,
validTransitionMap, verifyAbstractTransition,
verifyAbstractTransitionOrder)
import Ouroboros.Network.InboundGovernor.State (InboundGovernorState (..))
import Ouroboros.Network.InboundGovernor.Test.Utils
(allValidRemoteTransitionsNames, remoteStrIsFinalTransition,
validRemoteTransitionMap, verifyRemoteTransition,
Expand Down Expand Up @@ -126,6 +131,7 @@ tests =
, testProperty "no unsupported state" prop_inbound_governor_no_unsupported_state
, testProperty "pruning" prop_inbound_governor_pruning
, testProperty "counters" prop_inbound_governor_counters
, testProperty "InboundGovernorState" prop_inbound_governor_state
, testProperty "timeouts enforced" prop_timeouts_enforced
]
, testGroup "Server2"
Expand Down Expand Up @@ -626,6 +632,8 @@ multinodeExperiment
(AbstractTransitionTrace peerAddr))
-> Tracer m (WithName (Name peerAddr)
(InboundGovernorTrace peerAddr))
-> Tracer m (WithName (Name peerAddr)
(DebugInboundGovernor peerAddr))
-> Tracer m (WithName (Name peerAddr)
(ConnectionManagerTrace
peerAddr
Expand All @@ -641,7 +649,7 @@ multinodeExperiment
-> AcceptedConnectionsLimit
-> MultiNodeScript req peerAddr
-> m ()
multinodeExperiment inboundTrTracer trTracer inboundTracer cmTracer
multinodeExperiment inboundTrTracer trTracer inboundTracer debugTracer cmTracer
stdGen0 snocket makeBearer addrFamily serverAddr accInit
dataFlow0 acceptedConnLimit
(MultiNodeScript script _) =
Expand Down Expand Up @@ -773,7 +781,7 @@ multinodeExperiment inboundTrTracer trTracer inboundTracer cmTracer
Job ( withBidirectionalConnectionManager
name simTimeouts
inboundTrTracer trTracer cmTracer
inboundTracer
inboundTracer debugTracer
stdGen
snocket makeBearer (\_ -> pure ()) fd (Just localAddr) serverAcc
(mkNextRequests connVar)
Expand Down Expand Up @@ -1412,6 +1420,7 @@ prop_connection_manager_counters (Fixed rnd) serverAcc (ArbDataFlow dataFlow)
multinodeExperiment (sayTracer <> Tracer traceM)
(sayTracer <> Tracer traceM)
(sayTracer <> Tracer traceM)
nullTracer
( sayTracer
<> Tracer traceM
<> networkStateTracer getState)
Expand Down Expand Up @@ -1470,6 +1479,7 @@ prop_timeouts_enforced (Fixed rnd) serverAcc (ArbDataFlow dataFlow)
dynamicTracer
(tracerWithTime (Tracer traceM) <> dynamicTracer)
dynamicTracer
nullTracer
dynamicTracer

-- | Property wrapping `multinodeExperiment`.
Expand Down Expand Up @@ -1809,6 +1819,60 @@ prop_inbound_governor_counters (Fixed rnd) serverAcc (ArbDataFlow dataFlow)
events
(toNonFailing <$> attenuationMap)


prop_inbound_governor_state :: Fixed Int
-> Int
-> ArbDataFlow
-> AbsBearerInfo
-> MultiNodeScript Int TestAddr
-> Property
prop_inbound_governor_state (Fixed rnd) serverAcc (ArbDataFlow dataFlow)
defaultBearerInfo
mns@(MultiNodeScript events attenuationMap) =
let trace = runSimTrace sim

evs :: Trace (SimResult ()) (DebugInboundGovernor SimAddr)
evs = traceWithNameTraceEvents trace

-- inboundGovernorEvents :: Trace (SimResult ()) (InboundGovernorTrace SimAddr)
-- inboundGovernorEvents = traceWithNameTraceEvents trace

in counterexample (ppScript mns)
. getAllProperty
. bifoldMap
( \ case
MainReturn {} -> mempty
_ -> AllProperty (property False)
)
(AllProperty . inboundGovernorStateInvariant)
$ evs
where
sim :: IOSim s ()
sim = multiNodeSim (mkStdGen rnd) serverAcc dataFlow
defaultBearerInfo
maxAcceptedConnectionsLimit
events
attenuationMap

inboundGovernorStateInvariant :: DebugInboundGovernor SimAddr
-> Property
inboundGovernorStateInvariant
(DebugInboundGovernor InboundGovernorState { igsConnections,
igsMatureDuplexPeers,
igsFreshDuplexPeers })
=
keys === keys'
where
keys = Set.map remoteAddress
. Map.keysSet
. Map.filter (\ConnectionState { csDataFlow } -> csDataFlow == Duplex)
$ igsConnections

keys' = Set.fromList (OrdPSQ.keys igsFreshDuplexPeers)
<> Map.keysSet igsMatureDuplexPeers



-- | Property wrapping `multinodeExperiment` that has a generator optimized for triggering
-- pruning, and random generated number of connections hard limit.
--
Expand Down Expand Up @@ -2102,6 +2166,7 @@ unit_server_accept_error (Fixed rnd) ioErrType =
withBidirectionalConnectionManager "node-0" simTimeouts
nullTracer nullTracer
nullTracer nullTracer
nullTracer
(mkStdGen rnd)
snock
makeFDBearer
Expand Down Expand Up @@ -2162,6 +2227,8 @@ multiNodeSimTracer :: ( Alternative (STM m), Monad m, MonadFix m
(WithName (Name SimAddr) (AbstractTransitionTrace SimAddr))
-> Tracer m
(WithName (Name SimAddr) (InboundGovernorTrace SimAddr))
-> Tracer m
(WithName (Name SimAddr) (DebugInboundGovernor SimAddr))
-> Tracer m
(WithName
(Name SimAddr)
Expand All @@ -2173,7 +2240,7 @@ multiNodeSimTracer :: ( Alternative (STM m), Monad m, MonadFix m
multiNodeSimTracer stdGen serverAcc dataFlow defaultBearerInfo
acceptedConnLimit events attenuationMap
remoteTrTracer abstractTrTracer
inboundGovTracer connMgrTracer = do
inboundGovTracer debugTracer connMgrTracer = do

let attenuationMap' = (fmap toBearerInfo <$>)
. Map.mapKeys ( normaliseId
Expand All @@ -2189,6 +2256,7 @@ multiNodeSimTracer stdGen serverAcc dataFlow defaultBearerInfo
multinodeExperiment remoteTrTracer
abstractTrTracer
inboundGovTracer
debugTracer
connMgrTracer
stdGen
snocket
Expand Down Expand Up @@ -2223,8 +2291,8 @@ multiNodeSim :: (Serialise req, Show req, Eq req, Typeable req)
multiNodeSim stdGen serverAcc dataFlow defaultBearerInfo
acceptedConnLimit events attenuationMap = do
multiNodeSimTracer stdGen serverAcc dataFlow defaultBearerInfo acceptedConnLimit
events attenuationMap dynamicTracer dynamicTracer
dynamicTracer dynamicTracer
events attenuationMap dynamicTracer dynamicTracer dynamicTracer
(Tracer traceM) dynamicTracer


-- | Connection terminated while negotiating it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Ouroboros.Network.InboundGovernor
, withInboundGovernor
-- * Trace
, InboundGovernorTrace (..)
, DebugInboundGovernor (..)
, RemoteSt (..)
, RemoteTransition
, RemoteTransitionTrace
Expand Down Expand Up @@ -100,12 +101,13 @@ withInboundGovernor :: forall (muxMode :: MuxMode) socket initiatorCtx peerAddr
)
=> Tracer m (RemoteTransitionTrace peerAddr)
-> Tracer m (InboundGovernorTrace peerAddr)
-> Tracer m (DebugInboundGovernor peerAddr)
-> InboundGovernorInfoChannel muxMode initiatorCtx peerAddr versionData ByteString m a b
-> Maybe DiffTime -- protocol idle timeout
-> MuxConnectionManager muxMode socket initiatorCtx (ResponderContext peerAddr) peerAddr versionData versionNumber ByteString m a b
-> (Async m Void -> m (PublicInboundGovernorState peerAddr versionData) -> m x)
-> m x
withInboundGovernor trTracer tracer inboundInfoChannel
withInboundGovernor trTracer tracer debugTracer inboundInfoChannel
inboundIdleTimeout connectionManager k = do
-- State needs to be a TVar, otherwise, when catching the exception inside
-- the loop we do not have access to the most recent version of the state
Expand Down Expand Up @@ -497,6 +499,7 @@ withInboundGovernor trTracer tracer inboundInfoChannel

mask_ $ do
atomically $ writeTVar st state'
traceWith debugTracer (DebugInboundGovernor state')
case mbConnId of
Just cid -> traceWith trTracer (mkRemoteTransitionTrace cid state state')
Nothing -> pure ()
Expand Down Expand Up @@ -614,3 +617,7 @@ data InboundGovernorTrace peerAddr
-- ^ This case is unexpected at call site.
| TrInboundGovernorError !SomeException
deriving Show


data DebugInboundGovernor peerAddr = forall muxMode initiatorCtx versionData m a b.
DebugInboundGovernor (InboundGovernorState muxMode initiatorCtx peerAddr versionData m a b)
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ module Ouroboros.Network.InboundGovernor.Event

import Control.Applicative (Alternative)
import Control.Concurrent.Class.MonadSTM.Strict
import Control.Monad.Class.MonadTime.SI
import Control.Monad.Class.MonadThrow hiding (handle)
import Control.Monad.Class.MonadTime.SI

import Data.ByteString.Lazy (ByteString)
import Data.Functor (($>))
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Monoid.Synchronisation
import Data.Set qualified as Set
import Data.OrdPSQ (OrdPSQ)
import Data.Set qualified as Set

import Network.Mux qualified as Mux
import Network.Mux.Types (MiniProtocolDir (..), MiniProtocolStatus (..))
Expand Down
3 changes: 3 additions & 0 deletions ouroboros-network-framework/src/Ouroboros/Network/Server2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ data ServerArguments (muxMode :: MuxMode) socket initiatorCtx peerAddr versionD
serverTracer :: Tracer m (ServerTrace peerAddr),
serverTrTracer :: Tracer m (RemoteTransitionTrace peerAddr),
serverInboundGovernorTracer :: Tracer m (InboundGovernorTrace peerAddr),
serverDebugInboundGovernor :: Tracer m (DebugInboundGovernor peerAddr),
serverConnectionLimits :: AcceptedConnectionsLimit,
serverConnectionManager :: MuxConnectionManager muxMode socket initiatorCtx (ResponderContext peerAddr)
peerAddr versionData versionNumber bytes m a b,
Expand Down Expand Up @@ -137,6 +138,7 @@ with ServerArguments {
serverTrTracer,
serverTracer = tracer,
serverInboundGovernorTracer = inboundGovernorTracer,
serverDebugInboundGovernor,
serverConnectionLimits =
serverLimits@AcceptedConnectionsLimit { acceptedConnectionsHardLimit = hardLimit },
serverInboundIdleTimeout,
Expand All @@ -149,6 +151,7 @@ with ServerArguments {
traceWith tracer (TrServerStarted localAddresses)
withInboundGovernor serverTrTracer
inboundGovernorTracer
serverDebugInboundGovernor
serverInboundInfoChannel
serverInboundIdleTimeout
serverConnectionManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ import Ouroboros.Network.ConnectionManager.Types
import Ouroboros.Network.Context
import Ouroboros.Network.ControlMessage
import Ouroboros.Network.Driver.Limits
import Ouroboros.Network.InboundGovernor (InboundGovernorTrace (..))
import Ouroboros.Network.InboundGovernor (DebugInboundGovernor (..),
InboundGovernorTrace (..))
import Ouroboros.Network.Mux
import Ouroboros.Network.MuxMode
import Ouroboros.Network.Protocol.Handshake
Expand Down Expand Up @@ -429,6 +430,7 @@ withBidirectionalConnectionManager
peerAddr
(ConnectionHandlerTrace UnversionedProtocol DataFlowProtocolData)))
-> Tracer m (WithName name (InboundGovernorTrace peerAddr))
-> Tracer m (WithName name (DebugInboundGovernor peerAddr))
-> StdGen
-> Snocket m socket peerAddr
-> Mux.MakeBearer m socket
Expand All @@ -454,7 +456,7 @@ withBidirectionalConnectionManager
-> m a
withBidirectionalConnectionManager name timeouts
inboundTrTracer trTracer
cmTracer inboundTracer
cmTracer inboundTracer debugTracer
cmStdGen
snocket makeBearer
confSock socket
Expand Down Expand Up @@ -522,6 +524,8 @@ withBidirectionalConnectionManager name timeouts
WithName name `contramap` inboundTrTracer,
serverTracer =
WithName name `contramap` nullTracer, -- ServerTrace
serverDebugInboundGovernor =
WithName name `contramap` debugTracer,
serverInboundGovernorTracer =
WithName name `contramap` inboundTracer, -- InboundGovernorTrace
serverConnectionLimits = acceptedConnLimit,
Expand Down Expand Up @@ -722,7 +726,8 @@ unidirectionalExperiment stdGen timeouts snocket makeBearer confSock socket clie
timeLimitsHandshake maxAcceptedConnectionsLimit
$ \connectionManager ->
withBidirectionalConnectionManager "server" timeouts
nullTracer nullTracer nullTracer nullTracer
nullTracer nullTracer nullTracer
nullTracer nullTracer
stdGen''
snocket makeBearer
confSock socket Nothing
Expand Down Expand Up @@ -802,7 +807,7 @@ bidirectionalExperiment
nextRequests0 <- oneshotNextRequests clientAndServerData0
nextRequests1 <- oneshotNextRequests clientAndServerData1
withBidirectionalConnectionManager "node-0" timeouts
nullTracer nullTracer nullTracer
nullTracer nullTracer nullTracer nullTracer
nullTracer stdGen' snocket makeBearer confSock
socket0 (Just localAddr0)
[accumulatorInit clientAndServerData0]
Expand All @@ -811,7 +816,7 @@ bidirectionalExperiment
maxAcceptedConnectionsLimit
(\connectionManager0 _serverAddr0 _serverAsync0 -> do
withBidirectionalConnectionManager "node-1" timeouts
nullTracer nullTracer nullTracer
nullTracer nullTracer nullTracer nullTracer
nullTracer stdGen'' snocket makeBearer confSock
socket1 (Just localAddr1)
[accumulatorInit clientAndServerData1]
Expand Down
2 changes: 2 additions & 0 deletions ouroboros-network/src/Ouroboros/Network/Diffusion/P2P.hs
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,7 @@ runM Interfaces
serverSnocket = diNtcSnocket,
serverTracer = dtLocalServerTracer,
serverTrTracer = nullTracer, -- TODO: issue #3320
serverDebugInboundGovernor = nullTracer,
serverInboundGovernorTracer = dtLocalInboundGovernorTracer,
serverInboundIdleTimeout = Nothing,
serverConnectionLimits = localConnectionLimits,
Expand Down Expand Up @@ -1041,6 +1042,7 @@ runM Interfaces
serverSnocket = diNtnSnocket,
serverTracer = dtServerTracer,
serverTrTracer = dtInboundGovernorTransitionTracer,
serverDebugInboundGovernor = nullTracer,
serverInboundGovernorTracer = dtInboundGovernorTracer,
serverConnectionLimits = daAcceptedConnectionsLimit,
serverConnectionManager = connectionManager,
Expand Down

0 comments on commit 1a0f009

Please sign in to comment.