Skip to content

Commit 9645989

Browse files
authored
feat(simulation): support disabling the TCP congestion control modeling (#186)
1 parent 6d04e79 commit 9645989

File tree

6 files changed

+103
-31
lines changed

6 files changed

+103
-31
lines changed

data/simulation/config-idealised.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66

77
relay-strategy: "request-from-first"
88
tcp-congestion-control: false
9-
multiplex-mini-protocols: false
9+
multiplex-mini-protocols: true

simulation/ouroboros-leios-sim.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ library
4646
Chan.Driver
4747
Chan.Mux
4848
Chan.TCP
49+
Chan.Simple
4950
Diffusion
5051
ExamplesLayout
5152
ExamplesRelay

simulation/src/Chan.hs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module Chan (
2121
import Chan.Core
2222
import Chan.Driver
2323
import Chan.Mux
24+
import Chan.Simple (SimpleConnProps (..), newConnectionSimple)
2425
import Chan.TCP
2526
import Control.Concurrent.Class.MonadMVar (MonadMVar (..))
2627
import Control.Monad.Class.MonadAsync (MonadAsync)
@@ -40,11 +41,11 @@ mkConnectionConfig tcp mux tcpLatency maybeTcpBandwidth = ConnectionConfig{..}
4041
where
4142
transportConfig
4243
| tcp = TransportTcp (mkTcpConnProps tcpLatency (fromMaybe defaultTcpBandwidth maybeTcpBandwidth))
43-
| otherwise = TransportBasic
44+
| otherwise = TransportSimple (SimpleConnProps tcpLatency maybeTcpBandwidth)
4445
defaultTcpBandwidth = (kilobytes 1000)
4546

4647
data TransportConfig
47-
= TransportBasic
48+
= TransportSimple !SimpleConnProps
4849
| TransportTcp !TcpConnProps
4950

5051
newConnectionBundle ::
@@ -54,22 +55,15 @@ newConnectionBundle ::
5455
ConnectionConfig ->
5556
m (bundle (Chan m), bundle (Chan m))
5657
newConnectionBundle tracer = \case
57-
ConnectionConfig TransportBasic _mux@False ->
58+
ConnectionConfig (TransportSimple _simpleConnProps) _mux@False ->
5859
error "Unsupported configuration (no TCP, no mux)"
59-
ConnectionConfig TransportBasic _mux@True ->
60-
error "Unsupported configuration (no TCP)"
60+
ConnectionConfig (TransportSimple simpleConnProps) _mux@True -> do
61+
let tracer' = contramap ((fmap . fmap) fromBearerMsg) tracer
62+
(mA, mB) <- newConnectionSimple tracer' simpleConnProps
63+
(,) <$> newMuxChan mA <*> newMuxChan mB
6164
ConnectionConfig (TransportTcp _tcpConnProps) _mux@False ->
6265
error "Unsupported configuration (no mux)"
63-
ConnectionConfig (TransportTcp tcpConnProps) _mux@True ->
64-
newConnectionBundleTCPMux tracer tcpConnProps
65-
66-
newConnectionBundleTCPMux ::
67-
forall bundle m.
68-
(ConnectionBundle bundle, MonadTime m, MonadMonotonicTimeNSec m, MonadDelay m, MonadAsync m, MessageSize (BundleMsg bundle), MonadMVar m, MonadFork m) =>
69-
Tracer m (LabelTcpDir (TcpEvent (BundleMsg bundle))) ->
70-
TcpConnProps ->
71-
m (bundle (Chan m), bundle (Chan m))
72-
newConnectionBundleTCPMux tracer tcpprops = do
73-
let tracer' = contramap ((fmap . fmap) fromBearerMsg) tracer
74-
(mA, mB) <- newConnectionTCP tracer' tcpprops
75-
(,) <$> newMuxChan mA <*> newMuxChan mB
66+
ConnectionConfig (TransportTcp tcpConnProps) _mux@True -> do
67+
let tracer' = contramap ((fmap . fmap) fromBearerMsg) tracer
68+
(mA, mB) <- newConnectionTCP tracer' tcpConnProps
69+
(,) <$> newMuxChan mA <*> newMuxChan mB

simulation/src/Chan/Mux.hs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,7 @@ import STMCompat
2828
class ConnectionBundle bundle where
2929
type BundleMsg bundle
3030
toFromBundleMsgBundle :: bundle (ToFromBundleMsg (BundleMsg bundle))
31-
32-
traverseConnectionBundle ::
33-
Monad m =>
34-
(forall a. f a -> m (g a)) ->
35-
bundle f ->
36-
m (bundle g)
31+
traverseConnectionBundle :: Monad m => (forall a. f a -> m (g a)) -> bundle f -> m (bundle g)
3732

3833
-- | Injection, projection, between a common mux message type, and an
3934
-- individual message type. The following must hold:

simulation/src/Chan/Simple.hs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{-# LANGUAGE RecordWildCards #-}
2+
3+
module Chan.Simple (
4+
SimpleConnProps (..),
5+
newConnectionSimple,
6+
) where
7+
8+
import Chan.Core (Chan (..))
9+
import Chan.TCP (LabelTcpDir (..), MessageSize (..), RecvBuf, SendBuf, TcpEvent (..), TcpMsgForecast (..), mkChan, newRecvBuf, newSendBuf)
10+
import Control.Monad.Class.MonadAsync (MonadAsync (..))
11+
import Control.Tracer as Tracer (Contravariant (..), Tracer, traceWith)
12+
import ModelTCP (Bytes)
13+
import STMCompat
14+
import TimeCompat
15+
16+
data SimpleConnProps = SimpleConnProps
17+
{ latency :: DiffTime
18+
, bandwidthBytesPerSecond :: Maybe Bytes
19+
}
20+
21+
newConnectionSimple ::
22+
forall m a.
23+
(MonadTime m, MonadMonotonicTimeNSec m, MonadDelay m, MonadAsync m, MessageSize a) =>
24+
Tracer m (LabelTcpDir (TcpEvent a)) ->
25+
SimpleConnProps ->
26+
m (Chan m a, Chan m a)
27+
newConnectionSimple tracer simpleConnProps = do
28+
clientSendBuf <- newSendBuf
29+
serverSendBuf <- newSendBuf
30+
clientRecvBuf <- newRecvBuf
31+
serverRecvBuf <- newRecvBuf
32+
33+
_ <-
34+
async
35+
( transport
36+
(contramap DirClientToServer tracer)
37+
simpleConnProps
38+
clientSendBuf
39+
serverRecvBuf
40+
)
41+
_ <-
42+
async
43+
( transport
44+
(contramap DirServerToClient tracer)
45+
simpleConnProps
46+
serverSendBuf
47+
clientRecvBuf
48+
)
49+
50+
let clientChan, serverChan :: Chan m a
51+
clientChan = mkChan clientSendBuf clientRecvBuf
52+
serverChan = mkChan serverSendBuf serverRecvBuf
53+
54+
return (clientChan, serverChan)
55+
56+
transport ::
57+
(MonadSTM m, MonadMonotonicTimeNSec m, MonadDelay m, MessageSize a) =>
58+
Tracer m (TcpEvent a) ->
59+
SimpleConnProps ->
60+
SendBuf m a ->
61+
RecvBuf m a ->
62+
m ()
63+
transport tracer SimpleConnProps{..} sendbuf recvbuf = go
64+
where
65+
go = do
66+
msg <- atomically $ readTMVar sendbuf -- read now but keep buffer full
67+
now <- getMonotonicTime
68+
69+
let msgSize = messageSizeBytes msg
70+
msgSerialisationTime = maybe 0 (fromIntegral . (msgSize `div`)) bandwidthBytesPerSecond
71+
msgSendLeadingEdge = now
72+
msgSendTrailingEdge = msgSerialisationTime `addTime` now
73+
msgRecvLeadingEdge = latency `addTime` now
74+
msgRecvTrailingEdge = latency `addTime` msgSendTrailingEdge
75+
msgAcknowledgement = latency `addTime` msgRecvTrailingEdge
76+
let msgForecast = TcpMsgForecast{..}
77+
78+
-- schedule the arrival, and wait until it has finished sending
79+
atomically $ writeTQueue recvbuf (msgRecvTrailingEdge, msg)
80+
traceWith tracer (TcpSendMsg msg msgForecast [])
81+
threadDelay (msgSendTrailingEdge `diffTime` now)
82+
-- We keep the sendbuf full until the message has finished sending
83+
-- so that there's less buffering, and better simulates the TCP buffer
84+
-- rather than an extra app-level buffer.
85+
_ <- atomically $ takeTMVar sendbuf
86+
go

simulation/src/Chan/TCP.hs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@
33
{-# LANGUAGE ScopedTypeVariables #-}
44

55
module Chan.TCP (
6-
newConnectionTCP,
7-
MessageSize (..),
8-
Bytes,
9-
LabelTcpDir (..),
10-
TcpEvent (..),
11-
TcpConnProps (..),
6+
module Chan.TCP,
7+
module ModelTCP,
128
) where
139

1410
import Chan.Core (Chan (..))

0 commit comments

Comments
 (0)