Documentation
¶
Overview ¶
package sim is a simple implementation of a host using quic for transport. It's provided here to explain the transport capabilities required to drive `broadcast.Broadcaster` and must not be used in production.
Index ¶
- Constants
- type BandwidthEvent
- type BroadcastNode
- func (n *BroadcastNode) Addr() net.Addr
- func (n *BroadcastNode) BandwidthStats() (bytesSent, bytesReceived int)
- func (n *BroadcastNode) Close() error
- func (n *BroadcastNode) DialPeer(ctx context.Context, p int, addr net.Addr) error
- func (n *BroadcastNode) NodeNum() int
- func (n *BroadcastNode) Publish(messageID string, data []byte)
- func (n *BroadcastNode) Receive(ctx context.Context) (string, []byte, error)
- func (n *BroadcastNode) ResetBandwidthStats() (bytesSent, bytesReceived int)
- func (n *BroadcastNode) Start(ctx context.Context)
- type ChunkStats
- type Driver
- type EdgeSpec
- type GossipsubNode
- func (g *GossipsubNode) Addr() net.Addr
- func (g *GossipsubNode) BandwidthStats() (bytesSent, bytesReceived int)
- func (g *GossipsubNode) Close() error
- func (g *GossipsubNode) DialPeer(ctx context.Context, nodeNum int, addr net.Addr) error
- func (g *GossipsubNode) NodeNum() int
- func (g *GossipsubNode) Publish(messageID string, data []byte)
- func (g *GossipsubNode) Receive(ctx context.Context) (string, []byte, error)
- func (g *GossipsubNode) ResetBandwidthStats() (bytesSent, bytesReceived int)
- func (g *GossipsubNode) Start(ctx context.Context)
- type LogCollector
- type Node
- type NodeEvent
- type NodeSpec
- type Observer
- func (o *Observer) Chunks() ChunkStats
- func (o *Observer) OnChunkRcvd(_ broadcast.PeerID, _ broadcast.ChannelID, _ broadcast.MessageID, ...)
- func (o *Observer) OnChunkSent(_ broadcast.PeerID, channelID broadcast.ChannelID, ...)
- func (o *Observer) OnSessionStarted(channelID broadcast.ChannelID, messageID broadcast.MessageID, ...)
- func (o *Observer) Reset() ObserverSnapshot
- func (o *Observer) Stats() (originSent, relaySent int)
- type ObserverSnapshot
- type QUICHost
- type RSStrategyConfig
- type RunConfig
- type Scenario
- func (s *Scenario) Close()
- func (s *Scenario) NewLogCollector() *LogCollector
- func (s *Scenario) NewNode(ctx context.Context, nodeNum int) (Node, error)
- func (s *Scenario) NewStatsCollector() *StatsCollector
- func (s *Scenario) PushEventsTo(published, received chan NodeEvent, bandwidth chan BandwidthEvent)
- func (s *Scenario) RunNode(ctx context.Context, node Node, peers []int, publishWait time.Duration)
- func (s *Scenario) Start()
- type ScenarioStats
- type ShadowDriver
- type SimnetDriver
- func (s *SimnetDriver) BandwidthByRole() (origin, relay map[int]int)
- func (s *SimnetDriver) ChunkStatsByNode() map[int]ChunkStats
- func (s *SimnetDriver) Close() error
- func (s *SimnetDriver) NewNode(nodeNum int, logger *slog.Logger) (Node, error)
- func (s *SimnetDriver) NodeAddr(nodeNum int) net.Addr
- func (s *SimnetDriver) Start()
- func (s *SimnetDriver) TransportStats() (sent, received map[int]int)
- type SimulationConfig
- type StatsCollector
- type StrategyConfig
- type StrategyFunc
- type Topology
- type TopologyConfig
- type TopologyGenerate
- type TraceHeaderOptions
- type TraceWriter
- type TracingObserver
- func (o *TracingObserver) OnChunkError(err broadcast.ChunkProcessError)
- func (o *TracingObserver) OnChunkRcvd(peer broadcast.PeerID, channelID broadcast.ChannelID, ...)
- func (o *TracingObserver) OnChunkSent(peer broadcast.PeerID, channelID broadcast.ChannelID, ...)
- func (o *TracingObserver) OnPeerGone(peer broadcast.PeerID)
- func (o *TracingObserver) OnPeerHandshook(peer broadcast.PeerID, version broadcast.ProtocolVersion, ...)
- func (o *TracingObserver) OnPeerSubscribed(peer broadcast.PeerID, channelID broadcast.ChannelID)
- func (o *TracingObserver) OnPeerUnsubscribed(peer broadcast.PeerID, channelID broadcast.ChannelID)
- func (o *TracingObserver) OnPreambleOpened(peer broadcast.PeerID, channelID broadcast.ChannelID, ...)
- func (o *TracingObserver) OnRoutingUpdate(peer broadcast.PeerID, channelID broadcast.ChannelID, ...)
- func (o *TracingObserver) OnSessionDecoded(channelID broadcast.ChannelID, messageID broadcast.MessageID, ...)
- func (o *TracingObserver) OnSessionDisposed(channelID broadcast.ChannelID, messageID broadcast.MessageID, reason string)
- func (o *TracingObserver) OnSessionStarted(channelID broadcast.ChannelID, messageID broadcast.MessageID, ...)
- func (o *TracingObserver) OnStrategyProgress(channelID broadcast.ChannelID, messageID broadcast.MessageID, ...)
- type WorkloadConfig
Constants ¶
const DefaultListenPort = 8000
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BandwidthEvent ¶
type BandwidthEvent struct {
NodeNum int
SentBps int
ReceivedBps int
SentBytesTotal int
ReceivedBytesTotal int
At time.Time
}
BandwidthEvent represents a periodic bandwidth usage sample from a node.
type BroadcastNode ¶
type BroadcastNode struct {
// contains filtered or unexported fields
}
BroadcastNode wraps broadcast.Engine and a generic Channel to implement the Node interface. The generic Channel boundary is captured at construction via closures (publishFn, stopFn) and a receive channel.
func (*BroadcastNode) Addr ¶
func (n *BroadcastNode) Addr() net.Addr
func (*BroadcastNode) BandwidthStats ¶
func (n *BroadcastNode) BandwidthStats() (bytesSent, bytesReceived int)
func (*BroadcastNode) Close ¶
func (n *BroadcastNode) Close() error
func (*BroadcastNode) NodeNum ¶
func (n *BroadcastNode) NodeNum() int
func (*BroadcastNode) Publish ¶
func (n *BroadcastNode) Publish(messageID string, data []byte)
func (*BroadcastNode) ResetBandwidthStats ¶
func (n *BroadcastNode) ResetBandwidthStats() (bytesSent, bytesReceived int)
ResetBandwidthStats returns bytes sent/received since the last reset and advances the baseline.
func (*BroadcastNode) Start ¶
func (n *BroadcastNode) Start(ctx context.Context)
type ChunkStats ¶
ChunkStats holds per-node chunk reception verdict counts.
type Driver ¶
type Driver interface {
NewNode(nodeNum int, logger *slog.Logger) (Node, error)
NodeAddr(nodeNum int) net.Addr
Start()
Close() error
}
Driver abstracts node creation and network management across execution backends (Shadow, simnet).
type EdgeSpec ¶
type EdgeSpec struct {
Source int `json:"source" yaml:"source"`
Target int `json:"target" yaml:"target"`
LatencyMs int `json:"latency_ms" yaml:"latency_ms"`
}
EdgeSpec describes a directed edge in the topology.
type GossipsubNode ¶
type GossipsubNode struct {
// contains filtered or unexported fields
}
GossipsubNode implements the Node interface using libp2p's gossipsub protocol.
func (*GossipsubNode) Addr ¶
func (g *GossipsubNode) Addr() net.Addr
func (*GossipsubNode) BandwidthStats ¶
func (g *GossipsubNode) BandwidthStats() (bytesSent, bytesReceived int)
func (*GossipsubNode) Close ¶
func (g *GossipsubNode) Close() error
func (*GossipsubNode) NodeNum ¶
func (g *GossipsubNode) NodeNum() int
func (*GossipsubNode) Publish ¶
func (g *GossipsubNode) Publish(messageID string, data []byte)
func (*GossipsubNode) ResetBandwidthStats ¶
func (g *GossipsubNode) ResetBandwidthStats() (bytesSent, bytesReceived int)
func (*GossipsubNode) Start ¶
func (g *GossipsubNode) Start(ctx context.Context)
type LogCollector ¶
type LogCollector struct {
// contains filtered or unexported fields
}
LogCollector reads Published, Received, and Bandwidth events from a Scenario and logs them. Call Run in a goroutine before starting the node.
func (*LogCollector) Run ¶
func (c *LogCollector) Run(ctx context.Context)
type Node ¶
type Node interface {
Start(ctx context.Context)
Publish(messageID string, data []byte)
Receive(ctx context.Context) (messageID string, data []byte, err error)
DialPeer(ctx context.Context, nodeNum int, addr net.Addr) error
BandwidthStats() (sent, received int)
ResetBandwidthStats() (sent, received int)
Addr() net.Addr
NodeNum() int
Close() error
}
Node defines the interface for network simulation nodes.
func NewGossipsubNode ¶
func NewGossipsubNode(conn net.PacketConn, nodeNum int, logger *slog.Logger, tw *TraceWriter) (Node, error)
NewGossipsubNode creates a new GossipsubNode with QUIC transport.
type NodeSpec ¶
type NodeSpec struct {
Num int `json:"num" yaml:"num"`
UploadBWMbps int `json:"upload_bw_mbps" yaml:"upload_bw_mbps"`
DownloadBWMbps int `json:"download_bw_mbps" yaml:"download_bw_mbps"`
}
NodeSpec describes a node in the simulation topology.
type Observer ¶
type Observer struct {
broadcast.NoOpObserver
// contains filtered or unexported fields
}
Observer tracks bytes sent bucketed by session role (origin vs relay) and chunk reception verdicts. Embed NoOpObserver for methods we don't override.
func NewObserver ¶
func NewObserver() *Observer
func (*Observer) Chunks ¶
func (o *Observer) Chunks() ChunkStats
Chunks returns chunk reception verdict counts.
func (*Observer) OnChunkRcvd ¶
func (*Observer) OnChunkSent ¶
func (*Observer) OnSessionStarted ¶
func (*Observer) Reset ¶
func (o *Observer) Reset() ObserverSnapshot
Reset snapshots all counters and zeros them.
type ObserverSnapshot ¶
type ObserverSnapshot struct {
Chunks ChunkStats
OriginSent int
RelaySent int
}
ObserverSnapshot holds a point-in-time snapshot of all observer counters.
type QUICHost ¶
type QUICHost struct {
Transport *quic.Transport
Listener *quic.Listener
UDPAddr *net.UDPAddr
Config *quic.Config
}
QUICHost is QUIC transport and listener for ec broadcast. The host is provided for illustrating the transport requirements of an application that uses `broadcast.Broadcaster`.
func NewQUICHost ¶
func NewQUICHost(conn net.PacketConn) (QUICHost, error)
NewQUICHost creates a new `QUICHost`. The returned host listens for new connections on conn.
type RSStrategyConfig ¶
type RSStrategyConfig struct {
DataShards int `yaml:"data_shards"`
ParityShards int `yaml:"parity_shards"`
ChunkLen int `yaml:"chunk_len"`
ForwardMultiplier int `yaml:"forward_multiplier"`
EnableBitmaps bool `yaml:"enable_bitmaps"`
BitmapThreshold int `yaml:"bitmap_threshold"`
}
RSStrategyConfig holds RS-specific parameters.
type RunConfig ¶
type RunConfig struct {
Simulation SimulationConfig `yaml:"simulation"`
Strategy StrategyConfig `yaml:"strategy"`
Workload WorkloadConfig `yaml:"workload"`
Topology TopologyConfig `yaml:"topology"`
}
RunConfig is the unified YAML configuration for a simulation run.
func LoadRunConfig ¶
LoadRunConfig reads and parses a YAML run config from path.
func (*RunConfig) BuildTraceHeaderOptions ¶
func (rc *RunConfig) BuildTraceHeaderOptions(topo Topology) (TraceHeaderOptions, error)
func (*RunConfig) LoadTopology ¶
LoadTopology reads the topology JSON file referenced by Topology.File. Returns an error if File is empty (topology not yet generated).
type Scenario ¶
type Scenario struct {
NumMessages int
MessageSize int
Driver Driver
BandwidthLogFrequency time.Duration
Logger *slog.Logger
// contains filtered or unexported fields
}
Scenario orchestrates simulation test scenarios.
func (*Scenario) NewLogCollector ¶
func (s *Scenario) NewLogCollector() *LogCollector
func (*Scenario) NewStatsCollector ¶
func (s *Scenario) NewStatsCollector() *StatsCollector
func (*Scenario) PushEventsTo ¶
func (s *Scenario) PushEventsTo(published, received chan NodeEvent, bandwidth chan BandwidthEvent)
PushEventsTo registers channels to receive scenario events. Nil channels are ignored. Each call adds new channels; multiple consumers each get a copy of every event.
type ScenarioStats ¶
type ScenarioStats struct {
PublishedMessages map[broadcast.MessageID][]byte
PublishedAt map[broadcast.MessageID]time.Time
ReceivedMessages map[int]map[broadcast.MessageID][]byte // nodeNum → messageID → data
ReceivedAt map[int]map[broadcast.MessageID]time.Time // nodeNum → messageID → time
ReceivedLatency map[int]map[broadcast.MessageID]time.Duration // nodeNum → messageID → latency from PublishedAt
OriginBytesSent map[int]int // nodeNum → total bytes sent as origin
RelayBytesSent map[int]int // nodeNum → total bytes sent as relay
TransportBytesSent map[int]int // nodeNum → total bytes sent (transport level)
TransportBytesReceived map[int]int // nodeNum → total bytes received (transport level)
ChunksPerNode map[int]ChunkStats // nodeNum → chunk reception verdicts
}
ScenarioStats holds collected publish/receive data from a simulation run.
func RunSimnetScenario ¶
func RunSimnetScenario(ctx context.Context, s *Scenario, publishWait time.Duration) (ScenarioStats, error)
RunSimnetScenario runs a complete simnet scenario: creates nodes, wires them according to the topology, and returns collected stats.
type ShadowDriver ¶
type ShadowDriver struct {
Strategy StrategyFunc
TraceWriter *TraceWriter
// contains filtered or unexported fields
}
ShadowDriver implements Driver for Shadow simulation.
func (*ShadowDriver) NodeAddr ¶
func (s *ShadowDriver) NodeAddr(nodeNum int) net.Addr
NodeAddr resolves the address for a node in Shadow via DNS.
func (*ShadowDriver) Observer ¶
func (s *ShadowDriver) Observer() *Observer
Observer returns the observer for the node created by this driver.
type SimnetDriver ¶
type SimnetDriver struct {
Strategy StrategyFunc
Topology Topology
TraceWriter *TraceWriter
// contains filtered or unexported fields
}
SimnetDriver implements Driver for simnet-based testing.
func (*SimnetDriver) BandwidthByRole ¶
func (s *SimnetDriver) BandwidthByRole() (origin, relay map[int]int)
BandwidthByRole returns per-node origin and relay byte counts from the Observers injected into each node.
func (*SimnetDriver) ChunkStatsByNode ¶
func (s *SimnetDriver) ChunkStatsByNode() map[int]ChunkStats
ChunkStatsByNode returns per-node chunk reception verdicts.
func (*SimnetDriver) Close ¶
func (s *SimnetDriver) Close() error
Close shuts down the simnet simulation.
func (*SimnetDriver) NodeAddr ¶
func (s *SimnetDriver) NodeAddr(nodeNum int) net.Addr
NodeAddr returns the network address for a node.
func (*SimnetDriver) Start ¶
func (s *SimnetDriver) Start()
Start initializes the simnet simulation.
func (*SimnetDriver) TransportStats ¶
func (s *SimnetDriver) TransportStats() (sent, received map[int]int)
TransportStats returns per-node bytes sent and received at the transport (QUIC) level. Must be called before nodes are closed.
type SimulationConfig ¶
type SimulationConfig struct {
Driver string `yaml:"driver"`
LogLevel string `yaml:"log_level"`
LogFile string `yaml:"log_file,omitempty"`
TraceFile string `yaml:"trace_file,omitempty"`
BandwidthLogFrequencyMs int `yaml:"bandwidth_log_frequency_ms"`
}
SimulationConfig holds runtime/infrastructure settings.
func (*SimulationConfig) BandwidthLogFrequency ¶
func (c *SimulationConfig) BandwidthLogFrequency() time.Duration
type StatsCollector ¶
type StatsCollector struct {
// contains filtered or unexported fields
}
StatsCollector collects Published and Received events from a Scenario into a ScenarioStats. Call Run in a goroutine; it blocks until the context is cancelled and then returns the collected stats.
func (*StatsCollector) Run ¶
func (c *StatsCollector) Run(ctx context.Context) ScenarioStats
type StrategyConfig ¶
type StrategyConfig struct {
Name string
RS *RSStrategyConfig
}
StrategyConfig uses custom UnmarshalYAML to dispatch by name into the correct typed config. Only the matching strategy pointer is non-nil.
func (*StrategyConfig) UnmarshalYAML ¶
func (sc *StrategyConfig) UnmarshalYAML(value *yaml.Node) error
type StrategyFunc ¶
type StrategyFunc func(nodeNum int, conn net.PacketConn, logger *slog.Logger, obs broadcast.Observer, tw *TraceWriter) (Node, error)
StrategyFunc creates a simulation node.
func ECStrategy ¶
func ECStrategy[CI broadcast.ChunkIdent, R broadcast.Wire, P broadcast.Wire](scheme broadcast.Scheme[CI, R, P]) StrategyFunc
ECStrategy returns a StrategyFunc that creates broadcast nodes using the given erasure coding scheme. Engine, channel, and subscription setup are handled here; the scheme is the only varying part.
func GossipsubStrategy ¶
func GossipsubStrategy() StrategyFunc
GossipsubStrategy returns a StrategyFunc that creates gossipsub nodes.
type Topology ¶
type Topology struct {
Nodes []NodeSpec `json:"nodes" yaml:"nodes"`
Edges []EdgeSpec `json:"edges" yaml:"edges"`
}
Topology describes the network topology for simulation.
type TopologyConfig ¶
type TopologyConfig struct {
File string `yaml:"file,omitempty"`
Generate *TopologyGenerate `yaml:"generate,omitempty"`
}
TopologyConfig supports two mutually exclusive modes. Go only uses File; Generate is for the Python CLI.
type TopologyGenerate ¶
type TopologyGenerate struct {
NumNodes int `yaml:"num_nodes"`
Degree int `yaml:"degree"`
Type string `yaml:"type"`
Seed int `yaml:"seed"`
SuperNodeFraction float64 `yaml:"super_node_fraction"`
}
TopologyGenerate holds parameters for Python-side topology generation.
type TraceHeaderOptions ¶
type TraceWriter ¶
type TraceWriter struct {
// contains filtered or unexported fields
}
TraceWriter writes broadcast trace events as compact NDJSON. Safe for concurrent use from multiple goroutines.
func NewTraceWriter ¶
func NewTraceWriter(w io.Writer, t0 time.Time, nodes []string, topology Topology, config json.RawMessage) (*TraceWriter, error)
NewTraceWriter creates a TraceWriter and writes the header line.
func NewTraceWriterWithOptions ¶
func NewTraceWriterWithOptions(w io.Writer, t0 time.Time, nodes []string, topology Topology, config json.RawMessage, opts TraceHeaderOptions) (*TraceWriter, error)
NewTraceWriterWithOptions creates a TraceWriter and writes the header line.
func (*TraceWriter) Close ¶
func (tw *TraceWriter) Close() error
Close writes the footer and flushes.
func (*TraceWriter) WriteEvent ¶
WriteEvent writes a single event as a JSON array tuple.
type TracingObserver ¶
type TracingObserver struct {
*Observer
// contains filtered or unexported fields
}
TracingObserver implements broadcast.Observer by writing compact event tuples to a shared TraceWriter while also tracking stats via an embedded Observer.
func NewTracingObserver ¶
func NewTracingObserver(nodeIdx int, tw *TraceWriter) *TracingObserver
func (*TracingObserver) OnChunkError ¶
func (o *TracingObserver) OnChunkError(err broadcast.ChunkProcessError)
func (*TracingObserver) OnChunkRcvd ¶
func (*TracingObserver) OnChunkSent ¶
func (*TracingObserver) OnPeerGone ¶
func (o *TracingObserver) OnPeerGone(peer broadcast.PeerID)
func (*TracingObserver) OnPeerHandshook ¶
func (o *TracingObserver) OnPeerHandshook(peer broadcast.PeerID, version broadcast.ProtocolVersion, channels []broadcast.ChannelID)
func (*TracingObserver) OnPeerSubscribed ¶
func (o *TracingObserver) OnPeerSubscribed(peer broadcast.PeerID, channelID broadcast.ChannelID)
func (*TracingObserver) OnPeerUnsubscribed ¶
func (o *TracingObserver) OnPeerUnsubscribed(peer broadcast.PeerID, channelID broadcast.ChannelID)
func (*TracingObserver) OnPreambleOpened ¶
func (*TracingObserver) OnRoutingUpdate ¶
func (*TracingObserver) OnSessionDecoded ¶
func (*TracingObserver) OnSessionDisposed ¶
func (*TracingObserver) OnSessionStarted ¶
func (o *TracingObserver) OnSessionStarted(channelID broadcast.ChannelID, messageID broadcast.MessageID, role broadcast.SessionRole)
func (*TracingObserver) OnStrategyProgress ¶
type WorkloadConfig ¶
type WorkloadConfig struct {
NumMessages int `yaml:"num_messages"`
MessageSize int `yaml:"message_size"`
PublishWaitSeconds float64 `yaml:"publish_wait_seconds"`
StopTimeMinutes float64 `yaml:"stop_time_minutes"`
}
WorkloadConfig describes what to publish.
func (*WorkloadConfig) PublishWait ¶
func (c *WorkloadConfig) PublishWait() time.Duration
func (*WorkloadConfig) StopTime ¶
func (c *WorkloadConfig) StopTime() time.Duration