tssnet

user guide

Contents

Running tssnet
Scripts
Network model
Details of tssnet library
Creating a new network
Nodes
Links
Default routes
Tcp flows
Udp flows
Simulation
Link metrics
Tcp metrics
Udp metrics
Details of tssnet Python module
Class Network()
Class NetworkLogPlot()
Class NetworkPlotDynamic()

Running tssnet

This assumes that your platform has Python with matplotlib. (Easily installed via a distribution like Anaconda (cross-platform) or WinPython (Windows).)

To install tssnet, download (from here)

To simulate a network, you write a script that uses tssnet_0.py to construct the network, simulate it, and log and plot metrics.

Example scripts are here. To run any of them, say net-1.py, download the script and execute it in a directory containing the library and Python module. You should see plots as shown here. (Note: not tested within an IDE.)

Scripts

In general, a script imports tssnet_0.py (which imports the tssnet library) and then uses the functions provided by tssnet_0.py to construct a network, simulate it, and log and plot metrics.

The tssnet library has a C interface (so it can be used by any program that can link to a C library). Its functions are grouped into the following:

The Python module, tssnet_0.py, has three classes:

The typical structure of a script is as follows:

import tssnet_0.py

// create a network n
create an empty network n
add nodes to n
add links to n
set the default routes in n
add tcp flows to n
add udp flows to n

// simulate network n
set random seed for n
while "not done":
  update n by one timestep
  log the time and metrics of n

// plot metrics of n
plot logged metrics vs logged time

In the simulate stage, the "not done" condition can depend on the time and metrics of network n. For example: (time < 20 seconds) and (flow j's received data < 50000 bytes).

The calls to tssnet need not be in the above order. The stages can be interleaved. For example, immediately after a flow ends, one can start a new flow and continue simulating. The parameters and endpoints of the new flow can depend on the metrics achieved by the old flow.

One can also create multiple networks, and then simulate them in lock-step (updating all networks in each timestep), for example, to stop the simulation as soon as two similar networks diverge in their behavior.

Network model

A network with 6 nodes, 10 links, 1 tcp flow and 1 udp flow.

Conceptually, the nodes and links model the IP layer. There can be at most one link from one node to another. Links are unidirectional, so two links are needed for a bidirectional link between two nodes.

The tcp and udp flows model the application layer. Each flow has a source at one node that sends a given amount of data to a sink at another node, starting at a given time and using the relevant protocol (tcp or udp). There can be multiple tcp and udp flows from one node to another, and the flows can use different data and ack paths.

Limitations in tssnet_0:

Details of tssnet library

Creating a new network

create_network() creates an empty network and returns a pointer to it.

Nodes

add_node(n, nid) adds a node with integer id nid to network n.

Links

A link goes from one node (source) to another node (destination). There can be at most one link from one node to another. Conceptually, a link consists of a buffer and transmitter in the source node, and a wire from the source node to destination node. The buffer holds packets awaiting transmission. The wire holds packets in flight. The transmitter moves packets from buffer to wire.

add_link(n, srcnid, dstnid, rate, cvsq, buffersize, propdelay, cost) adds to network n a link with the following attributes:

  • srcnid: source node id.
  • dstnid: destination node id.
  • rate: rate (bytes/second) at which packets are sent from the buffer to the wire (i.e., link bandwidth).
  • cvsq, coefficient of variation squared of the transmit rate. This introduces statistical variation essential for realistic simulation. A small nonzero value suffices, e.g., 0.05.
  • buffersize: maximum number of bytes the buffer can hold.
  • propdelay: propagation delay (seconds), i.e., time taken by a packet to cross the wire.
  • cost: cost of the link for purposes of shortest-path routing.

Default routes

set_default_routes(n) sets the routing tables at nodes so that every node has a shortest-path route to every (reachable) destination. The cost of a route is the sum of the costs of the links of the route.

When a (tcp or udp) flow is added to the network, its data path (and ack path, if tcp) is set either to the default route or to an explictly-stated route. In either case, the flow's path does not change later (even if the default route subsequently changes due to adding new links).

Tcp flows

A tcp flow has a source at one node that sends a given amount of data to a sink at another node, starting at a given time and using the tcp protocol. The sink acks immediately and has unlimited receive window. The flow's "data path" (taken by the data packets) can be either the default route or explicitly specified. The same applies to the "ack path" (taken by ack packets).

add_tcp(n, srctype, srcnid, snknid, starttime, datasize) adds to network n a tcp flow that uses the default routes for its data and ack paths:

  • srctype: the type of tcp source: Tahoe, Reno, or NewReno.
  • srcnid: id of the node where the tcp source is located.
  • snknid: id of the node where the tcp sink is located.
  • starttime (seconds): time when the source starts sending.
  • datasize (bytes): the amount of data to send.

The function returns a positive integer that is the id of the tcp flow; no other flow (tcp or udp) in network n has that id. The return value is also the id of the flow's source. The return value + 1 is the id of the flow's sink.

add_tcp_with_route(n, srctype, datapath, datapathlen,
           ackpath, ackpathlen, starttime, datasize)

adds a tcp flow with explictly-stated data and ack paths. The parameters and return value are as in add_tcp() except that the following parameters replace srcnid and snknid:

  • datapath: array of node ids defining the data path (starting with the source node id and ending with the sink node id).
  • datapathlen: length of datapath (≥ 2)
  • ackpath: array of node ids defining the ack path (starting with the sink node id and ending with the source node id).
  • ackpathlen: length of ackpath (≥ 2)

Udp flows

A udp flow has a source at one node that sends a given amount of data at a fixed rate to a sink at another node, starting at a given time. The sink does not send acks. The flow's "data path" (taken by the data packets) can be either the default route or explicitly specified.

add_udp(n, srcnid, snknid, srcrate, starttime, datasize) adds to network n a udp flow that uses the default route for its data path:

  • srcnid: id of the node where the udp source is located.
  • snknid: id of the node where the udp sink is located.
  • srcrate: rate (bytes/second) at which the soure sends.
  • starttime (seconds): time when the source starts sending.
  • datasize (bytes): the amount of data to send.

The function returns a positive integer that is the id of the udp flow; no other flow (tcp or udp) in network n has that id. The return value is also the id of the flow's source. The return value + 1 is the id of the flow's sink.

add_udp_with_route(n, datapath, datapathlen, srcrate, starttime, datasize)
adds a udp flow with explictly-stated data paths. The parameters and return value are as in add_tcp() except that the following parameters replace srcnid and snknid:

  • datapath: array of node ids defining the data path (starting with the source node id and ending with the sink node id).
  • datapathlen: length of datapath (≥ 2)

Simulation

set_randomseed(n, seed) initializes the random number generator with seed. Use different seeds to see random variations in the metrics generated for the same network. Over tens of timesteps, the variation may be minor, but over hundreds of timesteps, they can be significant (see here).

update_network(n) updates the state of network n by one timestep and returns the updated simulation time. Thus the simulation time takes the values t0, t1, t2, …, where [t0, t1], [t1, t2], … are the timesteps.

Link metrics

Below are for a link with id j in network n.

get_inbuffsize(n, j) returns the number of bytes currently in the buffer of the link.

get_arrivedsize(n, j), when called at the end of a timestep, returns the number of bytes that arrived at the link in that timestep.

get_droppedsize(n, j), when called at the end of a timestep, returns the number of bytes that were dropped (due to buffer overflow) at the link in that timestep.

Tcp metrics

Below are for a tcp flow with id j in network n. Recall that its source has id j and its sink has id j+1.

get_sentsn(n, j) returns the current value of sentsn, defined as the highest data sequence number + 1 ever sent by the source.

get_ackdsn(n, j) returns the current value of ackdsn, the highest ack sequence number ever received by the source.

get_cwsize(n, j) returns the current value of cwsize, defined as the size (bytes) of the congestion window (at source).

get_sentsize(n, j) returns the current value of sentsize, defined as the total number of data bytes sent by the source (since the start).

get_rcvdsn(n, j+1) returns the current value of rcvdsn, defined as the data sequence number expected by the sink (i.e., the number of bytes of data delivered to the sink's local user).

get_rcvdsize(n, j+1) returns the current value of rcvdsize, defined as the total number of data bytes received by the sink (since the start).

Udp metrics

Below are for a udp flow with id j in network n. Recall that its source has id j and its sink has id j+1.

get_sentsn(n, j) returns the current value of sentsn, defined as the highest data sequence number + 1 ever sent by the source. (Same as for tcp.)

get_sentsize(n, j) returns the current value of sentsize, defined as the number of data bytes sent by the source since the start. (Same as for tcp.) Because this source does not retransmit or skip data, its sentsize and sentsn are always equal.

get_rcvdsn(n, j+1) returns the current value of rcvdsn, defined as the highest data sequence number ever received by the sink. (Differs from tcp.)

get_rcvdsize(n, j+1) returns the current value of rcvdsize, defined as the total number of data bytes received by the sink. (Same as for tcp.)

Details of tssnet Python module

tssnet_0.py has classes Network, NetworkLogPlot, and NetworkPlotDynamic.

Class Network()

This is a wrapper for the tssnet library.

Network()'s constructor wraps tssnet's create_network().
So "n = Network()" corresponds to "n = create_network()".

A method f(.) of Network() wraps tssnet's function f(n, .).
For example, "n.add_node(j)" corresponds to "add_node(n, j)".

There is a bit of garnish. In method add_link, parameter cost defaults to 1 (resuling in default routes being min-hop paths). In method add_tcp, parameter srctype is now a string and it defaults to 'NewReno'. In method add_tcp_with_route, parameter datapath is now a Python list and datapathlen is eliminated. And so on.

Class NetworkLogPlot()

This handles logging of metrics, generating plots of logged metrics (using matplotlib), dumping logs to file and restoring them (using pickle).

Logging

nlp = NetworkLogPlot(n), where n is a network, creates an instance for logging metrics of the network.

nlp.log_link(j, nm) tags link j of the network as a link to be logged under (string) name nm. (The name is used to identify the link in plots.)

Analogously, nlp.log_tcp(j, nm) tags tcp flow j of the network for logging, and nlp.log_udp(j, nm) tags udp flow j of the network for logging.

nlp.update_logs(t) reads the metrics of of all network components tagged for logging, and adds them to the log under time t. So t should be the current time, i.e., returned by the last call of " n.update_network()".

Plotting

nlp.plot_linklog(nm) displays one figure of one plot of logs of the link named nm, (i.e., a plot of [inbuffsize, arrivedsize, droppedsize] vs time). Does nothing if nm is not the name of a tagged link.

nlp.plot_linklogs(m, names), where m is a positive integer and names is a list of names of tagged links, generates one plot for each name in names, grouped into m plots per figure. So it generates a total of len(names)/m figures. Ignores entries in names that are not names of tagged links.

nlp.altplot_linklogs(names), where names is a list of names of tagged links, generates one figure with three plots: inbuffsize vs time, for all names in names; arrivedsize vs time, for all names in names; and droppedsize vs time, for all names in names. Ignores entries in names that are not names of tagged links.

nlp.plot_tcplog(nm), nlp.plot_tcplogs(m, names), and nlp.altplot_tcplogs(names) are the analogous methods for tcp flows.

nlp.plot_udplog(nm), nlp.plot_udplogs(m, names), and nlp.altplot_udplogs(names) are the analogous methods for udp flows.

Pickling

nlp.pickle_logs(pathname) dumps all the logs into file pathname.

nlp.pickle_logs(pathname) loads file pathname into the logs of nlp. Typically, you would not use nlp but a fresh instance, say x, created by x = NetworkLogPlot(None).

Class NetworkPlotDynamic()

This generates dynamic plots of a network simulation, i.e., without storing the metrics into a log (using matplotlib.Animation).
home user guide examples downloads