Exps. 1-4 CN - DCN
Exps. 1-4 CN - DCN
Exps. 1-4 CN - DCN
Installation
First, launch the PyCharm IDE terminal, and install simpy and ns.py using pip:
That's it! To upgrade Python packages in the current environment, run the command:
$ python upgrade_packages.py
Packet: a simple representation of a network packet, carrying its creation time, size, packet id, flow id, source and
destination.
DistPacketGenerator: generates packets according to provided distributions of inter-arrival times and packet sizes.
TracePacketGenerator: generates packets according to a trace file, with each row in the trace file representing a packet.
TCPPacketGenerator: generates packets using TCP as the transport protocol.
ProxyPacketGenerator: redirects real-world packets (with fixed packet sizes) into the simulation environment.
PacketSink: receives packets and records delay statistics.
TCPSink: receives packets, records delay statistics, and produces acknowledgements back to a TCP sender.
ProxySink: redirects all received packets to a destination real-world TCP server.
Port: an output port on a switch with a given rate and buffer size (in either bytes or the number of packets), using the
simple tail-drop mechanism to drop packets.
REDPort: an output port on a switch with a given rate and buffer size (in either bytes or the number of packets), using the
Early Random Detection (RED) mechanism to drop packets.
Wire: a network wire (cable) with its propagation delay following a given distribution. There is no need to model the
bandwidth of the wire, as that can be modeled by its upstream Port or scheduling server.
Splitter: a splitter that simply sends the original packet out of port 1 and sends a copy of the packet out of port 2.
NWaySplitter: an n-way splitter that sends copies of the packet to n downstream elements.
TrTCM: a two rate three color marker that marks packets as green, yellow, or red (refer to RFC 2698 for more details).
RandomDemux: a demultiplexing element that chooses the output port at random.
FlowDemux: a demultiplexing element that splits packet streams by flow ID.
FIBDemux: a demultiplexing element that uses a Flow Information Base (FIB) to make packet forwarding decisions based on
flow IDs.
TokenBucketShaper: a token bucket shaper.
TwoRateTokenBucketShaper: a two-rate three-color token bucket shaper with both committed and peak rates/burst sizes.
SPServer: a Static Priority (SP) scheduler.
WFQServer: a Weighted Fair Queueing (WFQ) scheduler.
DRRServer: a Deficit Round Robin (DRR) scheduler.
VirtualClockServer: a Virtual Clock scheduler.
SimplePacketSwitch: a packet switch with a FIFO bounded buffer on each of the outgoing ports.
FairPacketSwitch: a fair packet switch with a choice of a WFQ, DRR, Static Priority or Virtual Clock scheduler, as well as
bounded buffers, on each of the outgoing ports. It also shows an example how a simple hash function can be used to map
tuples of (flow_id, node_id, and port_id) to class IDs, and then use the parameter flow_classes to activate class-based
scheduling rather than flow_based scheduling.
1
PortMonitor: records the number of packets in a Port. The monitoring interval follows a given distribution.
ServerMonitor: records performance statistics in a scheduling server, such as WFQServer, VirtualClockServer, SPServer,
or DRRServer.
To design and implement new network components in this framework, you will first need to read the 10-minute SimPy tutorial. It
literally takes 10 minutes to read, but if that is still a bit too long, you can safely skip the section on Process Interaction, as this feature
will rarely be used in this network simulation framework.
In the Basic Concepts section of this tutorial, pay attention to three simple calls: env.process(), env.run(), and yield
env.timeout(). These are heavily used in this network simulation framework.
Setting up a process
The first is used in our component's constructor to add this component's run() method to the SimPy environment. For example,
in scheduler/drr.py:
self.action = env.process(self.run())
Keep in mind that not all network components need to be run as a SimPy process (more discussions on processes later). While traffic
shapers, packet generators, ports (buffers), port monitors, and packet schedulers definitely should be implemented as processes, a
flow demultiplexer, a packet sink, a traffic marker, or a traffic splitter do not need to be modeled as processes. They just represent
additional processing on packets inside a network.
Running a process
The second call, env.run(), is used by our examples to run the environment after connecting all the network components together.
For example, in examples/drr.py:
env.run(until=100)
This call simply runs the environment for 100 seconds.
Scheduling an event
The third call, yield env.timeout(), schedules an event to be fired sometime in the future. SimPy uses an ancient feature in Python
that's not well known, generator functions, to implement what it called processes. The term process is a bit confusing, as it has nothing
to do with processes in operating systems. In SimPy, each process is simply a sequence of timed events, and multiple processes occur
concurrently in real-time. For example, a scheduler is a process in a network, and so is a traffic shaper. The traffic shaper runs
concurrently with the scheduler, and both of these components run concurrently with other traffic shapers and schedulers in other
switches throughout the network.
In order to implement these processes in a network simulation, we almost always use the yield env.timeout() call.
Here, yield uses the feature of generator functions to return an iterator, rather than a value. This is just a fancier way of saying that
it yields the process in SimPy, allowing other processes to run for a short while, and it will be resumed at a later time specified by the
timeout value. For example, for a Deficit Round Robin (DRR) scheduler to send a packet (in scheduler/drr.py), it simply calls:
What a coincidence: the yield keyword in Python in generator functions is the same as the yield() system call in an operating
system kernel! This makes the code much more readable: whenever a process in SimPy needs to wait for a shared resource or a
timeout, simply call yield, just like calling a system call in an operating system.
2
Experiment - 1
Theory
A socket client requests for some resources to the socket server and the server responds to that request. So we
will design both server and client model so that each can communicate with them. The steps can be
considered like this -
Python socket server program executes at first and wait for any request.
Python socket client program will initiate the conversation at first.
Then server program will response accordingly to client requests.
Client program will
when client program terminates, this is optional and we can keep server program running
indefinitely or terminate with some specific command in client request.
Python Socket Server - We will save python socket server program as socket_server.py. To use python socket
connection, we need to import socket module. Then, sequentially we need to perform some task to establish
connection between server and client. We can obtain host address by using socket.gethostname() function. It
is recommended to user port address above 1024 because port number lesser than 1024 are reserved for
standard internet protocol. So our python socket server is running on port 5000 and it will wait for client
request
Python Socket Client - We will save python socket client program as socket_client.py. This program is
similar to the server program, except binding. The main difference between server and client program is, in
server program, it needs to bind host address and port address together.
(Ref- https://www.digitalocean.com/community/tutorials/python-socket-programming-server-client)
import socket
def client_program():
host = socket.gethostname() # as both code is running on same pc
3
port = 5000 # socket server port number
#57822.
if __name__ == '__main__':
client_program()
4
server_socket = socket.socket() # get instance
# look closely. The bind() function takes tuple as argument
server_socket.bind((host, port)) # bind host address and port together
if __name__ == '__main__':
server_program()
#To see the output, first run the socket server program. Then run the socket client program. After that, write
something from client program. Then again write reply from server program. At last, write bye from client
program to terminate both programs.
5
Client-Server model using Cisco Packet Tracer
6
Experiment - 2
7
# The following program generates a hybrid topological network based on Star &
Mesh topology, and uses Dijkstra's algorithm to find the shortest path in a
weighted and unweighted network.
import networkx as nx
import pylab as pl
g = nx.Graph()
g.add_edge('a', 'b', weight=0.1)
g.add_edge('b', 'c', weight=1.5)
g.add_edge('a', 'c', weight=1.0)
g.add_edge('c', 'd', weight=2.2)
pos = nx.spring_layout(g)
nx.draw_networkx_nodes(g, pos)
nx.draw_networkx_edges(g, pos)
nx.draw_networkx_labels(g, pos)
pl.show()
print(nx.shortest_path(g, 'b', 'd'))
print(nx.shortest_path(g, 'b', 'd', weight = 'weight'))
Output
8
['b', 'c', 'd']
['b', 'a', 'c', 'd']
9
Experiment - 3
Aim TCP Packet Generation and reception using ns.py and simpy packages in a Two-hop network.
Theory
Python Script
# A basic example that showcases how TCP can be used to generate packets, and how a TCP sink
# can send acknowledgment packets back to the sender in a simple two-hop network.
# (Refer ns.py/examples/tcp.py at main · TL-System/ns.py · GitHub)
# Install simpy using pip, and import
import simpy
# Install ns.py using pip
from ns.flow.cc import TCPReno
from ns.flow.cubic import TCPCubic
from ns.flow.flow import AppType, Flow
from ns.packet.tcp_generator import TCPPacketGenerator
from ns.packet.tcp_sink import TCPSink
from ns.port.wire import Wire
from ns.switch.switch import SimplePacketSwitch
def packet_arrival():
"""Packets arrive with a constant interval of 0.1 seconds."""
return 0.1
def packet_size():
"""The packets have a constant size of 1024 bytes."""
return 512
10
def delay_dist():
"""Network wires experience a constant propagation delay of 0.1 seconds."""
return 0.1
env = simpy.Environment()
flow = Flow(
fid=0,
src="flow 1",
dst="flow 1",
finish_time=10,
arrival_dist=packet_arrival,
size_dist=packet_size,
)
sender = TCPPacketGenerator(
env, flow=flow, cc=TCPReno(), element_id=flow.src, debug=True
)
switch = SimplePacketSwitch(
env,
nports=2,
port_rate=16384, # in bits/second
buffer_size=5, # in packets
debug=True,
)
11
receiver = TCPSink(env, rec_waits=True, debug=True)
sender.out = wire1_downstream
wire1_downstream.out = switch
wire2_downstream.out = receiver
receiver.out = wire2_upstream
wire2_upstream.out = switch
wire1_upstream.out = sender
env.run(until=100)
Output
..
.
.
Average throughput (last 10 packets): 2048.00 bytes/second.
Queue length at port: 0 packets.
TCPPacketGenerator flow 1 received ack till sequence number 35328 at time
39.1879.
TCPPacketGenerator flow 1 congestion window size = 1536.0, last ack = 35328.
TCPPacketGenerator flow 1 stopped timer 34816 at time 39.1879.
12
Experiment - 4
Aim TCP Packet Generation and reception using SimComponents.py user-defined library and simpy
package in a Two-hop network.
Theory
Python Script
# Install SimComponents.py or download from Discrete Event Simulation for Networking with
Python (grotto-networking.com)
from SimComponents import PacketGenerator, PacketSink
def constArrival2():
return 2.0
def distSize():
return expovariate(0.01)
1
pg2.out = ps
env.run(until=20)
Output
id: 1, src: HELLO, time: 1.5, size: 34.356269396815556