vnat

package
v0.0.0-...-bb1a4e7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2020 License: GPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package vnat is used to create virtual computer networks.

Index

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

func NewConnMat(numNodes int) *ConnMat

NewConnMat creates an all-zero connection matrix.

func (*ConnMat) Get

func (c *ConnMat) Get(src, dst int) float64

Get an entry in the matrix.

func (*ConnMat) NumNodes

func (c *ConnMat) NumNodes() int

NumNodes returns the number of nodes.

func (*ConnMat) ScaleDest

func (c *ConnMat) ScaleDest(dst int, scale float64)

ScaleDest scales a column of the matrix.

func (*ConnMat) ScaleSource

func (c *ConnMat) ScaleSource(src int, scale float64)

ScaleSource scales a row of the matrix.

func (*ConnMat) Set

func (c *ConnMat) Set(src, dst int, value float64)

Set an entry in the matrix.

func (*ConnMat) SumDest

func (c *ConnMat) SumDest(dst int) float64

SumDest sums a column of the matrix.

func (*ConnMat) SumSource

func (c *ConnMat) SumSource(src int) float64

SumSource sums 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

func (e *EventLoop) Go(f func(h *Handle))

Go runs a function in a Goroutine and passes it a new handle to the EventLoop.

func (*EventLoop) MustRun

func (e *EventLoop) MustRun() error

MustRun is like Run, but it panics if there is a deadlock.

func (*EventLoop) Run

func (e *EventLoop) Run() error

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.

func (*EventLoop) Time

func (e *EventLoop) Time() float64

Time gets the current virtual time.

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

type GreedyDropSwitcher struct {
	SendRates []float64
	RecvRates []float64
}

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

func (h *Handle) Cancel(t *Timer)

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.

func (*Handle) Schedule

func (h *Handle) Schedule(stream *EventStream, msg interface{}, delay float64) *Timer

Schedule creates a Timer for delivering an event.

func (*Handle) Sleep

func (h *Handle) Sleep(delay float64)

Sleep waits for a certain amount of virtual time to elapse.

type Message

type Message struct {
	Source  *Port
	Dest    *Port
	Message interface{}
	Size    float64
}

A Message is a chunk of data sent between nodes over a network.

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.

func NewNode

func NewNode() *Node

NewNode creates a new, unique Node.

func (*Node) Port

func (n *Node) Port(loop *EventLoop) *Port

Port creates a new Port connected to the Node.

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.

func (*Port) Recv

func (p *Port) Recv(h *Handle) *Message

Recv receives the next message.

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.

type Timer

type Timer struct {
	// contains filtered or unexported fields
}

A Timer controls the delayed delivery of an event. In particular, a Timer represents a single send that will happen in the (virtual) future.

func (*Timer) Time

func (t *Timer) Time() float64

Time gets the time when the timer will be fired.

If the virtual time is lower than a timer's Time(), then it is guaranteed that the timer has not fired.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL