sts Package

controller_manager Module

Convenience object for encapsulating and interacting with Controller processes

class sts.controller_manager.ControllerManager(controllers)[source]

Bases: object

Encapsulate a list of controllers objects

__init__(controllers)[source]
check_controller_processes_alive()[source]
controller_configs[source]
controllers[source]
down_controllers[source]
get_controller(cid)[source]
get_controller_by_label(label)[source]
kill_all()[source]
static kill_controller(controller)[source]
live_controllers[source]
static reboot_controller(controller)[source]

entities Module

This module defines the simulated entities, such as openflow switches, links, and hosts.

Bases: object

Represents a bidirectional edge: host <-> ingress switch

__init__(host, interface, switch, switch_port)[source]
class sts.entities.BigSwitchController(controller_config, sync_connection_manager, snapshot_service)[source]

Bases: sts.entities.Controller

__init__(controller_config, sync_connection_manager, snapshot_service)[source]
check_process_status()[source]
kill()[source]

Kill the process the controller is running in.

start()[source]
class sts.entities.Controller(controller_config, sync_connection_manager, snapshot_service)[source]

Bases: object

Encapsulates the state of a running controller.

__init__(controller_config, sync_connection_manager, snapshot_service)[source]

idx is the unique index for the controller used mostly for logging purposes.

check_process_status()[source]
cid[source]

Return the id of this controller. See ControllerConfig for more details.

kill()[source]

Kill the process the controller is running in.

label[source]

Return the label of this controller. See ControllerConfig for more details.

pid[source]

Return the PID of the Popen instance the controller was started with.

restart()[source]
start()[source]

Start a new controller process based on the config’s start_cmd attribute. Registers the Popen member variable for deletion upon a SIG* received in the simulator process.

class sts.entities.DeferredOFConnection(io_worker, cid, dpid, god_scheduler)[source]

Bases: pox.openflow.software_switch.OFConnection

__init__(io_worker, cid, dpid, god_scheduler)[source]
allow_message_receipt(ofp_message)[source]

Allow the message to actually go through to the switch

allow_message_send(ofp_message)[source]

Allow message actually be sent to the controller

get_controller_id()[source]
insert_pending_receipt(_, ofp_msg)[source]

Rather than pass directly on to the switch, feed into the god scheduler

send(ofp_message)[source]

Interpose on switch sends as well

set_message_handler(handler)[source]

Take the switch’s handler, and store it for later use

class sts.entities.FuzzSoftwareSwitch(dpid, name=None, ports=4, miss_send_len=128, n_buffers=100, n_tables=1, capabilities=None, can_connect_to_endhosts=True)[source]

Bases: pox.openflow.nx_software_switch.NXSoftwareSwitch

A mock switch implementation for testing purposes. Can simulate dropping dead.

__init__(dpid, name=None, ports=4, miss_send_len=128, n_buffers=100, n_tables=1, capabilities=None, can_connect_to_endhosts=True)[source]
add_controller_info(info)[source]
connect(create_connection, down_controller_ids=None)[source]
  • create_connection is a factory method for creating Connection objects

which are connected to controllers. Takes a ControllerConfig object and a reference to a switch (self) as a parameter

fail()[source]
get_connection(cid)[source]
recover(down_controller_ids=None)[source]
send(*args, **kwargs)[source]
serialize()[source]
class sts.entities.Host(interfaces, name='')[source]

Bases: pox.lib.revent.revent.EventMixin

A very simple Host entity.

For more sophisticated hosts, we should spawn a separate VM!

If multiple host VMs are too heavy-weight for a single machine, run the hosts on their own machines!

__init__(interfaces, name='')[source]
  • interfaces A list of HostInterfaces
dpid[source]
receive(interface, packet)[source]

Process an incoming packet from a switch

Called by PatchPanel

send(interface, packet)[source]

Send a packet out a given interface

class sts.entities.HostInterface(hw_addr, ip_or_ips=[], name='')[source]

Bases: object

Represents a host’s interface (e.g. eth0)

__init__(hw_addr, ip_or_ips=[], name='')[source]
static from_json(json_hash)[source]
port_no[source]
to_json()[source]

Bases: object

A network link between two switches

Temporary stand in for Murphy’s graph-library for the NOM.

Note: Directed!

__init__(start_software_switch, start_port, end_software_switch, end_port)[source]

Create a Link that is in the opposite direction of this Link.

class sts.entities.NamespaceHost(ip_addr_str, create_io_worker, name='', cmd='xterm')[source]

Bases: sts.entities.Host

A host that launches a process in a separate namespace process.

ETH_P_ALL = 3
__init__(ip_addr_str, create_io_worker, name='', cmd='xterm')[source]
  • ip_addr_str must be a string! not a IPAddr object
  • cmd: a string of the command to execute in the separate namespace The default is “xterm”, which opens up a new terminal window.
static get_eth_address_for_interface(ifname)[source]

Returns an EthAddr object from the interface specified by the argument.

interface is a string, commonly eth0, wlan0, lo.

receive(interface, packet)[source]

Process an incoming packet from a switch Called by PatchPanel

send(io_worker)[source]
class sts.entities.POXController(controller_config, sync_connection_manager, snapshot_service)[source]

Bases: sts.entities.Controller

__init__(controller_config, sync_connection_manager, snapshot_service)[source]
start()[source]

Start a new POX controller process based on the config’s start_cmd attribute. Registers the Popen member variable for deletion upon a SIG* received in the simulator process.

event_dag Module

class sts.event_dag.AtomicInput(failure, recovery)[source]

Bases: object

__init__(failure, recovery)[source]
label[source]
class sts.event_dag.EventDag(events, prefix_trie=None)[source]

Bases: object

A collection of Event objects. EventDags are primarily used to present a view of the underlying events with some subset of the input events pruned

__init__(events, prefix_trie=None)[source]

events is a list of EventWatcher objects. Refer to log_parser.parse to see how this is assembled.

atomic_input_events[source]
atomic_input_subset(subset)[source]

Return a view of the dag with only the subset remaining, where dependent input pairs remain together

compute_remaining_input_events(ignored_portion, events_list=None)[source]

ignore all input events in ignored_inputs, as well all of their dependent input events

events[source]

Return the events in the DAG

filter_unsupported_input_types()[source]
get_original_index_for_event(event)[source]
input_complement(subset, events_list=None)[source]

Return a view of the dag with everything except the subset and subset dependencies

input_events[source]
input_subset(subset)[source]

Return a view of the dag with only the subset and subset dependents remaining

insert_atomic_inputs(atomic_inputs, events_list=None)[source]

Insert inputs into events_list in the same relative order as the original events list. This method is needed because set union as used in delta debugging does not make sense for event sequences (events are ordered)

mark_invalid_input_sequences()[source]

Fill in domain knowledge about valid input sequences (e.g. don’t prune failure without pruning recovery.) Only do so if this isn’t a view of a previously computed DAG

next_state_change(index, events=None)[source]

Return the next ControllerStateChange that occurs at or after index.

update_migrations(remaining, ignored_portion, events_list)[source]

Walk through remaining input events, and update the source location of the host migration. For example, if one host migrates twice:

location A -> location B -> location C

And the first migration is pruned, update the second HostMigration event to look like:

location A -> location C

Note: mutates remaining

class sts.event_dag.EventDagView(parent, events_list)[source]

Bases: object

__init__(parent, events_list)[source]

subset is a list

add_inputs(inputs)[source]
atomic_input_events[source]
atomic_input_subset(subset)[source]

pre: subset must be a subset of only this view

events[source]

Return the events in the DAG

get_original_index_for_event(event)[source]
input_complement(subset)[source]
input_events[source]
input_subset(subset)[source]

pre: subset must be a subset of only this view

insert_atomic_inputs(inputs)[source]
next_state_change(index)[source]
sts.event_dag.migrations_per_host(events)[source]
sts.event_dag.replace_migration(replacee, old_location, new_location, event_list)[source]
sts.event_dag.split_list(l, split_ways)[source]

Split our inputs into split_ways separate lists

god_scheduler Module

class sts.god_scheduler.GodScheduler[source]

Bases: pox.lib.revent.revent.EventMixin

Models asynchrony: chooses when switches get to process packets from controllers. Buffers packets until they are pulled off the buffer and chosen by god (control_flow.py) to be processed.

__init__()[source]
flush()[source]

Garbage collect any previous pending messages

insert_pending_receipt(dpid, controller_id, ofp_message, conn)[source]

Called by DefferedOFConnection to insert messages into our buffer

insert_pending_send(dpid, controller_id, ofp_message, conn)[source]

Called by DefferedOFConnection to insert messages into our buffer

message_receipt_waiting(pending_message)[source]

Return whether the pending message receive is available

message_send_waiting(pending_message)[source]

Return whether the pending send is available

pending_receives()[source]

Return the message receipts which are waiting to be scheduled

pending_sends()[source]

Return the message sends which are waiting to be scheduled

schedule(pending_message)[source]

Cause the switch to process the pending message associated with the fingerprint and controller connection.

set_pass_through()[source]

Cause all message receipts to pass through immediately without being buffered

unset_pass_through()[source]

Unset pass through mode, and return any events that were passed through since pass through mode was set

class sts.god_scheduler.PendingMessage(pending_message, send_event=False)[source]

Bases: pox.lib.revent.revent.Event

__init__(pending_message, send_event=False)[source]
class sts.god_scheduler.PendingReceive

Bases: tuple

PendingReceive(dpid, controller_id, fingerprint)

controller_id

Alias for field number 1

dpid

Alias for field number 0

fingerprint

Alias for field number 2

class sts.god_scheduler.PendingSend

Bases: tuple

PendingSend(dpid, controller_id, fingerprint)

controller_id

Alias for field number 1

dpid

Alias for field number 0

fingerprint

Alias for field number 2

invariant_checker Module

class sts.invariant_checker.InvariantChecker(snapshotService)[source]

Bases: object

__init__(snapshotService)[source]
static check_connectivity(simulation)[source]

Return any pairs that couldn’t reach each other

static check_correspondence(simulation)[source]

Return if there were any policy-violations

static check_liveness(simulation)[source]

Very simple: have the controllers crashed?

static compute_controller_omega(controller_snapshot, live_switches, live_links, edge_links)[source]
static compute_physical_omega(live_switches, live_links, edge_links)[source]
static infer_policy_violations(physical_omega, controller_omega)[source]

Return if there were any missing entries

static python_check_blackholes(simulation)[source]
Do any switches:
  • send packets into a down link?
  • drop packets that are supposed to go out their in_port?

This method double checks whether it’s possible for any packets to fall into the blackhole in the first place.

Slightly different than check_connectivity. blackholes imply no connectivity, but not vice versa. No connectivity could also be due to:

  • a loop
  • PacketIn-based reactive routing
static python_check_connectivity(simulation)[source]
static python_check_loops(simulation)[source]
sts.invariant_checker.check_partitions(switches, live_links, access_links)[source]

replay_event Module

Classes representing events to be replayed. These events can be serialized to events.trace JSON files.

Note about the JSON events.trace format:

All events are serialized to JSON with the Event.to_json() method.

All events have a fingerprint field, which is used to compute functional equivalence between events across different replays of the trace.

The default format of the fingerprint field is a tuple (event class name,).

The specific format of the fingerprint field is documented in each class’ fingerprint() method.

The format of other additional fields is documented in each event’s __init__() method.

class sts.replay_event.CheckInvariants(label=None, round=-1, time=None, invariant_check_name='InvariantChecker.check_correspondence')[source]

Bases: sts.replay_event.InputEvent

Causes the simulation to pause itself and check the given invariant before proceeding.

__init__(label=None, round=-1, time=None, invariant_check_name='InvariantChecker.check_correspondence')[source]
Parameters:
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
  • invariant_check_name: unique name of the invariant to be checked. See config.invariant_checks for an exhaustive list of possible invariant checks.
static from_json(json_hash)[source]
proceed(simulation)[source]
to_json()[source]
class sts.replay_event.ConnectToControllers(label=None, round=-1, time=None, timeout_disallowed=False, prunable=False)[source]

Bases: sts.replay_event.InternalEvent

Logged at the beginning of the execution. Causes all switches to open TCP connections their their parent controller(s).

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.ControlChannelBlock(dpid, controller_id, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Simulates delay between switches and controllers by temporarily queuing all messages sent on the switch<->controller TCP connection. No messages will be sent over the connection until a ControlChannelUnblock occurs.

__init__(dpid, controller_id, label=None, round=-1, time=None)[source]
Parameters:
  • dpid: unique integer identifier of the switch.
  • controller_id: unique string label for the controller.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, dpid, controller id)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.ControlChannelUnblock(dpid, controller_id, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Unblocks the control channel delay triggered by a ControlChannelUnblock. All queued messages will be sent.

__init__(dpid, controller_id, label=None, round=-1, time=None)[source]
Parameters:
  • dpid: unique integer identifier of the switch.
  • controller_id: unique string label for the controller.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, dpid, controller id)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.ControlMessageBase(dpid, controller_id, fingerprint, label=None, round=-1, time=None, timeout_disallowed=False)[source]

Bases: sts.replay_event.InternalEvent

Logged whenever the GodScheduler decides to allow a switch to receive or send an openflow packet.

__init__(dpid, controller_id, fingerprint, label=None, round=-1, time=None, timeout_disallowed=False)[source]
Parameters:
  • dpid: unique integer identifier of the switch.
  • controller_id: unique string label for the controller.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
  • timeout_disallowed: whether the replayer should wait indefinitely for this event to occur. Defaults to False.
fingerprint[source]

Fingerprint tuple format: (class name, OFFingerprint, dpid, controller id) See fingerprints/messages.py for OFFingerprint format.

class sts.replay_event.ControlMessageReceive(dpid, controller_id, fingerprint, label=None, round=-1, time=None, timeout_disallowed=False)[source]

Bases: sts.replay_event.ControlMessageBase

Logged whenever the GodScheduler decides to allow a switch to receive an openflow message.

static from_json(json_hash)[source]
pending_receive[source]
proceed(simulation)[source]
class sts.replay_event.ControlMessageSend(dpid, controller_id, fingerprint, label=None, round=-1, time=None, timeout_disallowed=False)[source]

Bases: sts.replay_event.ControlMessageBase

Logged whenever the GodScheduler decides to allow a switch to send an openflow message.

static from_json(json_hash)[source]
pending_send[source]
proceed(simulation)[source]
class sts.replay_event.ControllerFailure(controller_id, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Kills a controller process with kill -9

__init__(controller_id, label=None, round=-1, time=None)[source]
Parameters:
  • controller_id: unique string label for the controller to be killed.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, controller id)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.ControllerRecovery(controller_id, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Reboots a crashed controller by reinvoking its original command line parameters

__init__(controller_id, label=None, round=-1, time=None)[source]
Parameters:
  • controller_id: unique string label for the controller.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, controller id)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.ControllerStateChange(controller_id, fingerprint, name, value, label=None, round=-1, time=None, timeout_disallowed=False)[source]

Bases: sts.replay_event.InternalEvent

Logged for any (visible) state change in the controller (e.g. mastership change). Visibility into controller state changes is obtained via syncproto.

__init__(controller_id, fingerprint, name, value, label=None, round=-1, time=None, timeout_disallowed=False)[source]
Parameters:
  • controller_id: unique string label for the controller.
  • name: The format string passed to the controller’s logging library.
  • value: An array of values for the format string.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
  • timeout_disallowed: whether the replayer should wait indefinitely for this event to occur. Defaults to False.
fingerprint[source]

Fingerprint tuple format: (class name, PendingStateChange.fingerprint, controller id) PendingStateChange.fingerprint is the format string passed to the controller’s logging library (without interpolated values)

static from_json(json_hash)[source]
static from_pending_state_change(state_change)[source]
pending_state_change[source]
proceed(simulation)[source]
class sts.replay_event.DataplaneDrop(fingerprint, label=None, round=-1, time=None, passive=True)[source]

Bases: sts.replay_event.InputEvent

Removes an in-flight dataplane packet with the given fingerprint from the network.

__init__(fingerprint, label=None, round=-1, time=None, passive=True)[source]
Parameters:
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
  • passive: whether we’re using Replayer.DataplaneChecker
fingerprint[source]

Fingerprint tuple format: (class name, DPFingerprint, switch dpid, port no) See fingerprints/messages.py for format of DPFingerprint.

static from_json(json_hash)[source]
proceed(simulation)[source]
to_json()[source]
class sts.replay_event.DataplanePermit(fingerprint, label=None, round=-1, time=None, passive=True)[source]

Bases: sts.replay_event.InternalEvent

DataplanePermit allows a packet to move from one port to another in the dataplane. We basically just keep this around for bookkeeping purposes. During replay, this let’s us know which packets to let through, and which to drop.

__init__(fingerprint, label=None, round=-1, time=None, passive=True)[source]
Parameters:
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
  • passive: whether we’re using Replayer.DataplaneChecker
fingerprint[source]

Fingerprint tuple format: (class name, DPFingerprint, switch dpid, port no) See fingerprints/messages.py for format of DPFingerprint.

static from_json(json_hash)[source]
proceed(simulation)[source]
to_json()[source]
class sts.replay_event.DeterministicValue(controller_id, name, value, label=None, round=-1, time=None, timeout_disallowed=False)[source]

Bases: sts.replay_event.InternalEvent

Logged whenever the controller asks for a deterministic value (e.g. gettimeofday()

__init__(controller_id, name, value, label=None, round=-1, time=None, timeout_disallowed=False)[source]
Parameters:
  • controller_id: unique string label for the controller.
  • name: name of the DeterministicValue request, e.g. “gettimeofday”
  • value: the return value of the DeterministicValue request.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
  • timeout_disallowed: whether the replayer should wait indefinitely for this event to occur. Defaults to False.
static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.Event(prefix='e', label=None, round=-1, time=None, dependent_labels=None, prunable=True)[source]

Bases: object

Superclass for all event types.

__init__(prefix='e', label=None, round=-1, time=None, dependent_labels=None, prunable=True)[source]
fingerprint[source]

All events must have a fingerprint. Fingerprints are used to compute functional equivalence.

proceed(simulation)[source]

Executes a single `round’. Returns a boolean that is true if the Replayer may continue to the next Event, otherwise proceed() again later.

to_json()[source]

Convert the event to json format

class sts.replay_event.HostMigration(old_ingress_dpid, old_ingress_port_no, new_ingress_dpid, new_ingress_port_no, host_id, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Migrates a host from one location in network to another. Creates a new virtual port on the new switch, and takes down the old port on the old switch.

__init__(old_ingress_dpid, old_ingress_port_no, new_ingress_dpid, new_ingress_port_no, host_id, label=None, round=-1, time=None)[source]
Parameters:
  • old_ingress_dpid: unique integer identifier of the ingress switch the host is moving away from.
  • old_ingress_port_no: integer identifier of the port the host is moving away from.
  • new_ingress_dpid: unique integer identifier of the ingress switch the host is moving to.
  • new_ingress_port_no: integer identifier of the port the host is moving to.
  • host_id: unique integer identifier of the host.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, old dpid, old port, new dpid, new port, host id)

static from_json(json_hash)[source]
new_location[source]
old_location[source]
proceed(simulation)[source]
class sts.replay_event.InputEvent(label=None, round=-1, time=None, dependent_labels=None, prunable=True)[source]

Bases: sts.replay_event.Event

An InputEvents is an event that the simulator injects into the simulation.

Each InputEvent has a list of dependent InternalEvents that it takes in its constructor. This enables us to properly prune events.

`InputEvents’ may also be referred to as ‘external events’, elsewhere in documentation or code.

__init__(label=None, round=-1, time=None, dependent_labels=None, prunable=True)[source]
class sts.replay_event.InternalEvent(label=None, round=-1, time=None, timeout_disallowed=False, prunable=False)[source]

Bases: sts.replay_event.Event

An InternalEvent is one that happens within the controller(s) under simulation. Derivatives of this class verify that the internal event has occured during replay in its proceed method before it returns.

__init__(label=None, round=-1, time=None, timeout_disallowed=False, prunable=False)[source]
disallow_timeouts()[source]
proceed(simulation)[source]
class sts.replay_event.InvariantViolation(violations, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.SpecialEvent

Class for logging violations as json dicts

__init__(violations, label=None, round=-1, time=None)[source]
Parameters:
  • violations: an array of strings specifying the invariant violation fingerprints. Format of the strings depends on the invariant check. Empty array means there were no violations.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
static from_json(json_hash)[source]
class sts.replay_event.LinkDiscovery(controller_id, link_attrs, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Deprecated

__init__(controller_id, link_attrs, label=None, round=-1, time=None)[source]
fingerprint[source]
static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.LinkFailure(start_dpid, start_port_no, end_dpid, end_port_no, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Cuts a link between switches. This causes the switch to send an ofp_port_status message to its parent(s). All packets forwarded over this link will be dropped until a LinkRecovery occurs.

__init__(start_dpid, start_port_no, end_dpid, end_port_no, label=None, round=-1, time=None)[source]
Parameters:
  • start_dpid: unique integer identifier of the first switch connected to the link.
  • start_port_no: integer port number of the start switch’s port.
  • end_dpid: unique integer identifier of the second switch connected to the link.
  • end_port_no: integer port number of the end switch’s port to be created.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, start dpid, start port_no, end dpid, end port_no)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.LinkRecovery(start_dpid, start_port_no, end_dpid, end_port_no, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Recovers a failed link between switches. This causes the switch to send an ofp_port_status message to its parent(s).

__init__(start_dpid, start_port_no, end_dpid, end_port_no, label=None, round=-1, time=None)[source]
Parameters:
  • start_dpid: unique integer identifier of the first switch connected to the link.
  • start_port_no: integer port number of the start switch’s port.
  • end_dpid: unique integer identifier of the second switch connected to the link.
  • end_port_no: integer port number of the end switch’s port to be created.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, start dpid, start port, end dpid, end port)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.PendingStateChange[source]

Bases: sts.replay_event.PendingStateChange

class sts.replay_event.PolicyChange(request_type, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Not currently supported

__init__(request_type, label=None, round=-1, time=None)[source]
static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.SpecialEvent(prefix='e', label=None, round=-1, time=None, dependent_labels=None, prunable=True)[source]

Bases: sts.replay_event.Event

proceed(_)[source]
class sts.replay_event.SwitchFailure(dpid, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Crashes a switch, by disconnecting its TCP connection with the controller(s).

__init__(dpid, label=None, round=-1, time=None)[source]
Parameters:
  • dpid: unique integer identifier of the switch.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, dpid)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.SwitchRecovery(dpid, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Recovers a crashed switch, by reconnecting its TCP connection with the controller(s).

__init__(dpid, label=None, round=-1, time=None)[source]
Parameters:
  • dpid: unique integer identifier of the switch.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
fingerprint[source]

Fingerprint tuple format: (class name, dpid)

static from_json(json_hash)[source]
proceed(simulation)[source]
class sts.replay_event.TrafficInjection(label=None, dp_event=None, host_id=None, round=-1, time=None, prunable=True)[source]

Bases: sts.replay_event.InputEvent

Injects a dataplane packet into the network at the given host’s access link

__init__(label=None, dp_event=None, host_id=None, round=-1, time=None, prunable=True)[source]
Parameters:
  • dp_event: DataplaneEvent object encapsulating the packet contents and the access link.
  • host_id: unique integer label identifying the host that generated the packet.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
  • prunable: whether this input event can be pruned during delta debugging.
fingerprint[source]

Fingerprint tuple format: (class name, dp event, host_id) The format of dp event is: {“interface”: HostInterface.to_json(), “packet”: base 64 encoded packet contents} See entities.py for the HostInterface json format.

static from_json(json_hash)[source]
proceed(simulation)[source]
to_json()[source]
class sts.replay_event.WaitTime(wait_time, label=None, round=-1, time=None)[source]

Bases: sts.replay_event.InputEvent

Causes the simulation to sleep for the specified number of seconds. Controller processes continue running during this time.

__init__(wait_time, label=None, round=-1, time=None)[source]
Parameters:
  • wait_time: float representing how long to sleep in seconds.
  • label: a unique label for this event. Internal event labels begin with ‘i’ and input event labels begin with ‘e’.
  • time: the timestamp of when this event occured. Stored as a tuple: [seconds since unix epoch, microseconds].
  • round: optional integer. Indicates what simulation round this event occured in.
static from_json(json_hash)[source]
proceed(simulation)[source]
sts.replay_event.assert_fields_exist(json_hash, *args)[source]

assert that the fields exist in json_hash

sts.replay_event.dictify_fingerprint(fingerprint)[source]
sts.replay_event.extract_base_fields(json_hash)[source]
sts.replay_event.extract_label_time(json_hash)[source]

simulation_state Module

Encapsulates the state of the simulation, including:
  • The controllers
  • The topology
  • Dataplane forwarding
  • (Optionally) the dataplane trace
  • Metadata (e.g. # of failures)
class sts.simulation_state.Simulation(topology, controller_manager, dataplane_trace, god_scheduler, io_master, patch_panel, controller_sync_callback, multiplex_sockets)[source]

Bases: object

Encapsulates the running state of a single simulation:
  • Topology (network state)
  • Controller processes
  • GodScheduler (OpenFlow messages)
  • PatchPanel (Dataplane messages)
  • RecordingSyncCallback (controller state changes)
  • Dataplane Trace (pending dataplane messages)
__init__(topology, controller_manager, dataplane_trace, god_scheduler, io_master, patch_panel, controller_sync_callback, multiplex_sockets)[source]
clean_up()[source]

Ensure that state from previous runs (old controller processes, sockets, IOLoop object) are cleaned before the next time we bootstrap

connect_to_controllers()[source]

Connect all switches to all controllers

io_master[source]
set_exit_code(code)[source]
set_pass_through()[source]

Set to pass-through during bootstrap, so that switch initialization messages don’t get buffered

unset_pass_through()[source]

unset pass-through mode

class sts.simulation_state.SimulationConfig(controller_configs=None, topology_class=<class 'sts.topology.FatTree'>, topology_params='', patch_panel_class=<class 'sts.topology.BufferedPatchPanel'>, dataplane_trace=None, snapshot_service=None, multiplex_sockets=False)[source]

Bases: object

Maintains the configuration for:
  • The controllers: a list of ControllerConfig objects
  • The topology
  • Patch panel (dataplane forwarding)
  • (Optionally) the dataplane trace
  • Initialization parameters (switch_init_sleep_seconds)
__init__(controller_configs=None, topology_class=<class 'sts.topology.FatTree'>, topology_params='', patch_panel_class=<class 'sts.topology.BufferedPatchPanel'>, dataplane_trace=None, snapshot_service=None, multiplex_sockets=False)[source]
Constructor parameters:
topology_class => a sts.topology.Topology class (not object!)
defining the switches and links
topology_params => Comma-delimited list of arguments to pass into the FatTree
constructor, specified just as you would type them within the parens.

patch_panel_class => a sts.topology.PatchPanel class (not object!) dataplane_trace => a path to a dataplane trace file

(e.g. dataplane_traces/ping_pong_same_subnet.trace)
switch_init_sleep_seconds => number of seconds to wait for switches to
connect to controllers before starting the simulation. Defaults to False (no wait).
monkey_patch_select => whether to use STS’s custom deterministic
select. Requires that the controller is monkey-patched too
bootstrap(sync_callback)[source]

Return a simulation object encapsulating the state of the system in its initial starting point: - boots controllers - connects switches to controllers

May be invoked multiple times!

set_dataplane_trace_path(path)[source]

snapshot Module

class sts.snapshot.BigSwitchSnapshotService[source]

Bases: sts.snapshot.SnapshotService

__init__()[source]
fetchSnapshot(controller)[source]
class sts.snapshot.FlexibleNOMDecoder[source]
__init__()[source]
decode(json)[source]
decode_action(json)[source]
decode_entry(json)[source]
decode_flow_table(json)[source]
decode_match(json)[source]
decode_switch(json)[source]
class sts.snapshot.PoxSnapshotService[source]

Bases: sts.snapshot.SnapshotService

__init__()[source]
fetchSnapshot(controller)[source]
class sts.snapshot.Snapshot[source]

Bases: object

A Snapshot object is a description of the controllers’ view of the network in terms that are meaningful to the debugger. Any snaphsot grabbed from any controller should be transformed into a Snapshot object in order to be fed to HSA

class sts.snapshot.SnapshotService[source]

Bases: object

Controller-specific SnapshotServices take care of grabbing a snapshot from their controller in whatever format the controller exports it, and translating it into a Snaphot object that is meaningful to the debbuger

__init__()[source]
fetchSnapshot(controller)[source]
class sts.snapshot.SyncProtoSnapshotService[source]

Bases: sts.snapshot.SnapshotService

__init__()[source]
fetchSnapshot(controller)[source]
sts.snapshot.get_snapshotservice(controller_configs)[source]

Return a SnapshotService object determined by the name of the first controller in the controller_configs.

For now, we only support a homogenous controller environment.

topology Module

If the user does not specify a topology to test on, use by default a full mesh of switches, with one host connected to each switch. For example, with N = 3:

controller
host1 host2
switch1-(1)————(3)–switch2

/ (2) (4)

/
/
/
(6)-switch3-(5)

host3

class sts.topology.BufferedPatchPanel(switches, hosts, connected_port_mapping)[source]

Bases: sts.topology.PatchPanel, pox.lib.revent.revent.EventMixin

A Buffered Patch panel.Listens to SwitchDPPacketOut and HostDpPacketOut events, and re-raises them to listeners of this object. Does not traffic until given permission from a higher-level.

__init__(switches, hosts, connected_port_mapping)[source]
drop_dp_event(dp_event)[source]

Given a SwitchDpPacketOut event, remove it from our buffer, and do not forward. Return the dropped event.

get_buffered_dp_event(fingerprint)[source]
permit_dp_event(dp_event)[source]

Given a SwitchDpPacketOut event, permit it to be forwarded

queued_dataplane_events[source]
sts.topology.BufferedPatchPanelForTopology(topology)[source]

Given a pox.lib.graph.graph object with hosts, switches, and other things, produce an appropriate BufferedPatchPanel

class sts.topology.FatTree(num_pods=4, create_io_worker=None, gui=False)[source]

Bases: sts.topology.Topology

Construct a FatTree topology with a given number of pods

Bases: sts.topology.LinkTracker

__init__(port2access_link, interface2access_link, port2internal_link, dpid2switch)[source]
FatTree.__init__(num_pods=4, create_io_worker=None, gui=False)[source]
FatTree.construct_tree(num_pods)[source]

According to “A Scalable, Commodity Data Center Network Architecture”, k = number of ports per switch = number of pods number core switches = (k/2)^2 number of edge switches per pod = k / 2 number of agg switches per pod = k / 2 number of hosts attached to each edge switch = k / 2 number of hosts per pod = (k/2)^2 total number of hosts = k^3 / 4

FatTree.install_default_routes()[source]

Install static routes as proposed in Section 3 of “A Scalable, Commodity Data Center Network Architecture”. This is really a strawman routing scheme. PORTLAND, et. al. are much better

FatTree.install_portland_routes()[source]

We use a modified version of PORTLAND. We make two changes: OpenFlow 1.0 doesn’t support prefix matching on MAC addresses, so we use IP addresses instead. (same # of flow entries, and we don’t model flooding anyway) Second, we ignore vmid and assume 8 bit pod ids. So, IPs are of the form: 123.pod.position.port

FatTree.wire_tree(access_links, network_links)[source]
class sts.topology.LinkTracker(dpid2switch, port2access_link, interface2access_link, port2internal_link)[source]

Bases: object

__init__(dpid2switch, port2access_link, interface2access_link, port2internal_link)[source]

Create an access link between a host and a switch If no interface is provided, an unused interface is used If no port is provided, an unused port is used

Create a unidirectional network (internal) link between two switches If a port is not provided, an unused port in the corresponding switch is used

find_unused_interface(host)[source]

Find a host’s unused interface; if no such interface exists, create a new one

find_unused_port(switch)[source]

Find a switch’s unused port; if no such port exists, create a new one

migrate_host(old_ingress_dpid, old_ingress_portno, new_ingress_dpid, new_ingress_portno)[source]

Migrate the host from the old (ingress switch, port) to the new (ingress switch, port). Note that the new port must not already be present, otherwise an exception will be thrown (we treat all switches as configurable software switches for convenience, rather than hardware switches with a fixed number of ports)

port_connected(port)[source]

Return whether the port is currently connected to anything

Remove an access link between a host and a switch

Remove a unidirectional network (internal) link between two switches

class sts.topology.MeshTopology(num_switches=3, create_io_worker=None, netns_hosts=False, gui=False)[source]

Bases: sts.topology.Topology

Bases: sts.topology.LinkTracker

A factory method (inner class) for creating a fully meshed network. Connects every pair of switches. Ports are in ascending order of the dpid of connected switch, while skipping the self-connections. I.e., for (dpid, portno):

(0, 0) <-> (1,0) (2, 1) <-> (1,1)
__init__(dpid2switch, access_links=[])[source]
MeshTopology.__init__(num_switches=3, create_io_worker=None, netns_hosts=False, gui=False)[source]

Populate the topology as a mesh of switches, connect the switches to the controllers

Optional argument(s):
  • num_switches. The total number of switches to include in the mesh
  • netns_switches. Whether to create network namespace hosts instead of normal hosts.
class sts.topology.PatchPanel(switches, hosts, connected_port_mapping)[source]

Bases: object

A Patch panel. Contains a bunch of wires to forward packets between switches. Listens to the SwitchDPPacketOut event on the switches.

__init__(switches, hosts, connected_port_mapping)[source]
Constructor
  • switches: a list of the switches in the network

  • hosts: a list of hosts in the network

  • connected_port_mapping: a function which takes (switch_no, port_no, dpid2switch),

    and returns the adjacent (node, port) or None

deliver_packet(host, packet, host_interface)[source]

Deliver the packet to its final destination

forward_packet(next_switch, packet, next_port)[source]

Forward the packet to the given port

get_connected_port(node, port)[source]
handle_DpPacketOut(event)[source]
class sts.topology.Topology(create_io_worker=None, gui=False)[source]

Bases: object

Abstract base class of all topology types. Wraps the edges and vertices of the network.

__init__(create_io_worker=None, gui=False)[source]
block_connection(connection)[source]
blocked_controller_connections[source]
connect_to_controllers(controller_info_list, create_connection)[source]

Bind sockets from the software_switchs to the controllers. For now, assign each switch to the next controller in the list in a round robin fashion.

Controller info list is a list of ControllerConfig tuples
  • create_io_worker is a factory method for creating IOWorker objects. Takes a socket as a parameter
  • create_connection is a factory method for creating Connection objects which are connected to controllers. Takes a ControllerConfig object as a parameter
crash_switch(software_switch)[source]
create_host(ingress_switch_or_switches, mac_or_macs=None, ip_or_ips=None, get_switch_port=<function get_switchs_host_port at 0x403f5f0>)[source]

Create a host, register it in the topology, and wire it to the given switch(es)

create_switch(switch_id, num_ports, can_connect_to_endhosts=True)[source]

Create a switch and register it in the topology

get_host(hid)[source]
get_switch(dpid)[source]
hosts[source]
live_edge_switches[source]

Return the software_switchs which are currently up and can connect to hosts

live_switches[source]

Return the software_switchs which are currently up

migrate_host(old_ingress_dpid, old_ingress_portno, new_ingress_dpid, new_ingress_portno)[source]
ok_to_send(dp_event)[source]

Return True if it is ok to send the dp_event arg

static populate_from_topology(graph)[source]

Take a pox.lib.graph.graph.Graph and generate arguments needed for the simulator

recover_switch(software_switch, down_controller_ids=None)[source]
remove_host(host)[source]

Remove a host and all associated access links

remove_switch(switch)[source]

Remove a switch, along with all associated links and any dangling hosts previously attached

reset()[source]

Reset topology without new controllers

switches[source]
unblock_connection(connection)[source]
unblocked_controller_connections[source]
sts.topology.create_host(ingress_switch_or_switches, mac_or_macs=None, ip_or_ips=None, get_switch_port=<function get_switchs_host_port at 0x403f5f0>)[source]

Create a Host, wired up to the given ingress switches

sts.topology.create_netns_host(create_io_worker, ingress_switch, ip_addr_str='', get_switch_port=<function get_switchs_host_port at 0x403f5f0>, cmd='xterm')[source]

Create a host with a process running in a separate network namespace. The netns can only communicate with a single interface (for now) because it must correspond to the physical interface in the network namespace guest.

Because there is only 1 logical interface possible, this means that there can only be 1 switch as well.

  • ip_addr_str must be a string! not a IpAddr object
sts.topology.create_switch(switch_id, num_ports, can_connect_to_endhosts=True)[source]
sts.topology.get_switchs_host_port(switch)[source]

Return the switch’s ofp_phy_port connected to the host

traffic_generator Module

class sts.traffic_generator.TrafficGenerator(random=<random.Random object at 0x52a6be0>)[source]

Bases: object

Generate sensible randomly generated (openflow) events

__init__(random=<random.Random object at 0x52a6be0>)[source]
generateAndInject(packet_type, host, self_pkt=False)[source]
icmp_ping(interface, destination_interface)[source]
set_hosts(hosts)[source]

Let us know how to set the destination addresses