Documentation ¶
Overview ¶
Package vnat is used to create virtual computer networks.
Index ¶
- type ConnMat
- func (c *ConnMat) Get(src, dst int) float64
- func (c *ConnMat) NumNodes() int
- func (c *ConnMat) ScaleDest(dst int, scale float64)
- func (c *ConnMat) ScaleSource(src int, scale float64)
- func (c *ConnMat) Set(src, dst int, value float64)
- func (c *ConnMat) SumDest(dst int) float64
- func (c *ConnMat) SumSource(src int) float64
- type Event
- type EventLoop
- type EventStream
- type GreedyDropSwitcher
- type Handle
- type Message
- type Network
- type Node
- type Port
- type RandomNetwork
- type Switcher
- type SwitcherNetwork
- type Timer
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ConnMat ¶
type ConnMat struct {
// contains filtered or unexported fields
}
A ConnMat is a connectivity matrix.
Entries in the matrix indicate a transfer rate from a source node (row) to a destination node (column).
func NewConnMat ¶
NewConnMat creates an all-zero connection matrix.
func (*ConnMat) ScaleSource ¶
ScaleSource scales a row of the matrix.
type Event ¶
type Event struct { Message interface{} Stream *EventStream }
An Event is a message received on some EventStream.
type EventLoop ¶
type EventLoop struct {
// contains filtered or unexported fields
}
An EventLoop is a global scheduler for events in a simulated distributed system.
All Goroutines which access an EventLoop should be started using the EventLoop.Go() method.
The event loop will only run when all active Goroutines are polling for an event. This way, simulated machines don't have to worry about real timing while performing computations.
Example ¶
loop := NewEventLoop() stream := loop.Stream() loop.Go(func(h *Handle) { msg := h.Poll(stream).Message fmt.Println(msg, h.Time()) }) loop.Go(func(h *Handle) { message := "Hello, world!" delay := 15.5 h.Schedule(stream, message, delay) }) loop.MustRun()
Output: Hello, world! 15.5
func NewEventLoop ¶
func NewEventLoop() *EventLoop
NewEventLoop creates an event loop.
The event loop's clock starts at 0.
func (*EventLoop) Go ¶
Go runs a function in a Goroutine and passes it a new handle to the EventLoop.
func (*EventLoop) Run ¶
Run runs the loop and blocks until all handles have been closed.
It is not safe to run the loop from more than one Goroutine at once.
Returns with an error if there is a deadlock.
func (*EventLoop) Stream ¶
func (e *EventLoop) Stream() *EventStream
Stream creates a new EventStream.
type EventStream ¶
type EventStream struct {
// contains filtered or unexported fields
}
An EventStream is a uni-directional channel of events that are passed through an EventLoop.
It is only safe to use an EventStream on one EventLoop at once.
type GreedyDropSwitcher ¶
A GreedyDropSwitcher emulates a switch where outgoing data is spread evenly across a node's outputs, and inputs to a node are dropped uniformly at random when a node is oversubscribed.
This is equivalent to first normalizing the rows of a connection matrix, and then normalizing the columns.
func NewGreedyDropSwitcher ¶
func NewGreedyDropSwitcher(numNodes int, rate float64) *GreedyDropSwitcher
NewGreedyDropSwitcher creates a GreedyDropSwitcher with uniform upload and download rates across all nodes.
func (*GreedyDropSwitcher) NumNodes ¶
func (g *GreedyDropSwitcher) NumNodes() int
NumNodes gets the number of nodes the switch expects.
func (*GreedyDropSwitcher) SwitchedRates ¶
func (g *GreedyDropSwitcher) SwitchedRates(mat *ConnMat)
SwitchedRates performs the switching algorithm.
type Handle ¶
type Handle struct { *EventLoop // contains filtered or unexported fields }
A Handle is a Goroutine's mechanism for accessing an EventLoop. Goroutines should not share Handles.
func (*Handle) Cancel ¶
Cancel stops a timer if the timer is scheduled.
If the timer is not scheduled, this has no effect.
func (*Handle) Poll ¶
func (h *Handle) Poll(streams ...*EventStream) *Event
Poll waits for the next event from a set of streams.
type Network ¶
type Network interface { // Send message objects from one node to another. // The message will arrive on the receiving port's // incoming EventStream if the communication is // successful. // // This is a non-blocking operation. // // It is preferrable to pass multiple messages in at // once, if possible. // Otherwise, the Network may have to continually // re-plan the entire message delivery timeline. Send(h *Handle, msgs ...*Message) }
A Network represents an abstract way of communicating between nodes.
Example ¶
loop := NewEventLoop() // A switch with two ports that do I/O at 2 bytes/sec. switcher := NewGreedyDropSwitcher(2, 2.0) node1 := NewNode() node2 := NewNode() latency := 0.25 network := NewSwitcherNetwork(switcher, []*Node{node1, node2}, latency) port1 := node1.Port(loop) port2 := node2.Port(loop) // Goroutine for node 1. loop.Go(func(h *Handle) { message := port1.Recv(h).Message.(string) response := strings.ToUpper(message) // Simulate time it took to do the calculation. h.Sleep(0.125) network.Send(h, &Message{ Source: port1, Dest: port2, Message: response, Size: float64(len(message)), }) }) // Goroutine for node 2. loop.Go(func(h *Handle) { msg := "this should be capitalized" network.Send(h, &Message{ Source: port2, Dest: port1, Message: msg, Size: float64(len(msg)), }) response := port2.Recv(h).Message.(string) fmt.Println(response, h.Time()) }) _ = loop.MustRun()
Output: THIS SHOULD BE CAPITALIZED 26.625
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
A Node represents a machine on a virtual network.
type Port ¶
type Port struct { // The Node to which the Port is attached. Node *Node // A stream of *Message objects. Incoming *EventStream }
A Port identifies a point of communication on a Node. Data is sent from Ports and received on Ports.
type RandomNetwork ¶
type RandomNetwork struct{}
A RandomNetwork is a network that assigns random delays to every message.
func (RandomNetwork) Send ¶
func (r RandomNetwork) Send(h *Handle, msgs ...*Message)
Send sends the messages with random delays.
type Switcher ¶
type Switcher interface { // Apply the switching algorithm to compute the // transfer rates of every connection. // // The mat argument is passed in with 1's wherever a // node wants to send data to another node, and 0's // everywhere else. // // When the function returns, mat indicates the rate // of data between every pair of nodes. SwitchedRates(mat *ConnMat) }
A Switcher is a switching algorithm that determines how rapidly data flows in a graph of nodes. One job of the Switcher is to decide how to deal with oversubscription.
type SwitcherNetwork ¶
type SwitcherNetwork struct {
// contains filtered or unexported fields
}
A SwitcherNetwork is a network where data is passed through a Switcher. Multiple messages along the same edge are sent concurrently, potentially making each one take longer to arrive at its destination.
func NewSwitcherNetwork ¶
func NewSwitcherNetwork(switcher Switcher, nodes []*Node, latency float64) *SwitcherNetwork
NewSwitcherNetwork creates a new SwitcherNetwork.
The latency argument adds an extra constant-length timeout to every message delivery. The latency period does influence oversubscription, so one message's latency period may interfere with another message's transmission. In practice, this may result in twice the latency-based congestion that would actually occur in a network.
func (*SwitcherNetwork) Send ¶
func (s *SwitcherNetwork) Send(h *Handle, msgs ...*Message)
Send sends the message over the network.
This may affect the speed of messages that are already being transmitted.