Python 3
SimPy 3. It is built for simulations where there are many objects being simulated and they interact often.
id
: packet idsource
: Source Device ipdestination
: Destination Device ip
DataPacket has no additional variables or methods
AckPacket has no additional variables or methods
distance_table
: table of distances calculated by the sending routerbuffer_occ
: occupancy of the buffer the packet is being sent downlink
: the link the packet is being sent down
specify_link(link)
: set thelink
the router packet came from.
ip
: the ip address of the devicelinks
: an array of links attached to the device as [Link, Link, ...]
add_link(link)
: add the link tolinks
receive_packet(Packet)
: different implementations for Router and Host, but depending on the packet, call a handler function.
distance_table
: maps each destination ip to the cost it takes to get thererouting_table
: maps each destination ip to the next hop the packet must take to get
route(Packet)
: if the packet is not aRouterPacket
, then send it along. Otherwise pass it toreceive_router(packet)
send_router()
: senddistance_table
in aRouterPacket
to all neighborsreceive_router(RoutingPacket -> (neighbor_distance_table, link, buff_occ))
:- For each
device
inneighbor_distance_table
:
- If
device
is not inrouting_table
, updaterouting_table
anddistance_table
withlink
andneighbor_distance_table[device]
- If
routing_table[device] == link
(i.e. we already use this link to get todevice
), updatedistance_table
usingneighbor_distance_table
andbuff_occ
- If
neighbor_distance_table[device] + buff_occ < distance_table[device]
(i.e. there is a new, better path), then updaterouting_table
anddistance_table
to include this
- If
routing_table
has changed, callsend_router()
- For each
window
: the current flight stored as [start, end)window_size
: the maximum flight sizelast_acknowledged
: the last packet id acknowledged and the number of times it was acknowledged stored as (id, count)
send_data(packet_id, destination)
: send the packet down the attached linkretransmit()
: send the last unacknowledged packetstart_flow(data, destination, tcp_type)
: depending on thetcp_type
, call the tcp specific flow function
ss_thresh
: the slow start threshold past which the flow enters congestion controltimeout_clock
: stores the average travel time and deviation as (travel_time, deviation)timer
: a separate process waiting for a timeout to occur
-
get_timeout()
: returns how long the current timer should wait -
reset_timer()
:- Wait for however long
get_timeout()
says and
- If interrupted before completion, set
timer = reset_timer()
(i.e. reset the timer) - If not interrupted, assume failure and
- Call
retransmit()
- Set
ss_thresh = window_size / 2
- Set
window_size = 1
- Set
window = [window.start, window.start + 1)
- Set
timer = reset_timer()
(i.e. reset the timer)
- Call
- Wait for however long
-
start_reno_flow(data, destination)
:- Initializes
window_size = 1
- Initializes
window = [start = 0, end = 0)
- Initializes
ss_thresh = inf
- Initializes
last_acknowledged = (id = 0, count = 0)
- Sends a packet, sets
window = [0, 1)
, setstimer = reset_timer()
(i.e. starts the timer), and waits for reactivation - Each time the function is reactivated, it sends
window_size - len(window)
number of data packets todestination
if there is anydata
left to send
- Initializes
-
update_timeout_clock(send_time, arrival_time)
: update the average travel time and deviation stored intimeout_clock
-
receive_reno_ack(Ack_Packet -> (p_id))
:- If the acknowledgment is the next expected one, call
update_timeout_clock(Ack_Packet.send_time, current_time)
- If the acknowledgment is higher than the last ack received, set
last_acknowledged = (p_id, 1)
andwindow = [p_id, window.end)
and resettimer
- If in fast recovery (
last_acknowledged.number >= 4
), setwindow_size = ss_thresh
- If in slow-start (
window_size <= ss_thresh
), setwindow_size += 1
- If in congestion control (
window_size > ss_thresh
), setwindow_size += 1 / window_size
- If it is equal to the last ack received, set
last_acknowledged = (p_id, last_acknowledged.number + 1)
- If this is less than the fourth duplicate acknowledgment
- If currently in slow-start, set
window_size += 1
- If currently in congestion control, set
window_size += 1 / window_size
- If currently in slow-start, set
- If this is the fourth duplicate acknowledgment
- Call
retransmit()
- Set
ss_thresh = window_size / 2
- Set
window_size = window_size / 2 + 3
- reset
timer
- Call
- If this is more than the fourth duplicate acknowledgment
- Set
window_size += 1
- Set
- If it is less than the last ack received, ignore it
- If
len(window) < window_size
(i.e. the current flight size is less than the maximum allowed), then reactivatestart_reno_flow
- If the acknowledgment is the next expected one, call
fast_RTT
: the smallest and most recent round-trip-time stored as (smallest, most_recent)timer
: a separate process that updates the window size
-
update_window()
:- every 20 milliseconds, update the window size based on
fast_RTT.smallest
andfast_RTT.most_recent
- If
len(window) < window_size
(i.e. the current flight size is less than the maximum allowed), then reactivatestart_fast_flow
- every 20 milliseconds, update the window size based on
-
start_fast_flow(data, destination)
- Initializes
window_size = 1
- Initializes
window = [start = 0, end = 0)
- Initializes
fast_RTT = (smallest = inf, most_recent = inf)
- Initializes
last_acknowledged = (id = 0, count = 0)
- Sends a packet, sets
window = [0, 1)
, setstimer = update_window()
(i.e. starts the window updater), and waits for reactivation - Each time the function is reactivated, it sends
window_size - len(window)
number of data packets todestination
if there is anydata
left to send
- Initializes
-
update_rtt(send_time, arrival_time)
: updatefast_RTT
based on the new RTT -
receive_fast_ack(Ack_Packet -> (p_id))
:- If the acknowledgment is the next expected one, call
update_rtt(Ack_Packet.send_time, current_time)
- If the acknowledgment is higher than the last one received, set
last_acknowledged = (p_id, 1)
andwindow = [p_id, window.end)
- If
len(window) < window_size
(i.e. the current flight size is less than the maximum allowed), then reactivatestart_fast_flow
- If the acknowledgment is the next expected one, call
received
: array of received packets stored as [id_1, id_2, ...]
-
send_ack(p_id, source)
: send an acknowledgment packet down the link back to the source -
get_next_ack():
find the first hole in the acknowledgment sequence and return that id -
receive_data(DataPacket -> p_id)
:- If
p_id
is not inreceived
- Add it to
received
- Get
next_id = get_next_ack()
- Call
send_ack(next_id, DataPacket.source)
- Add it to
- If
p_id
is inreceived
, ignore it
- If
Reno has no additional variables or methods for the receiver.
FAST has no additional variables or methods for the receiver.
devices
: a list of attached to this link as [Device, Device]buffer
: a queue of packetslink_rate
: number specifying the rate at which packets can be transmittedlink_delay
: number specifying the travel time from one end of the link to the otherbuffer_size
: number specifying how many packets can sit in the queue before packets begin to be dropped
add_device(device)
: adddevice
todevices
insert_into_buffer(packet)
: add the packet to the bufferremove_from_buffer(packet)
: remove the packet to the buffersend_packet(packet, source)
:- If there is any room in the buffer, add the packet to the buffer using
insert_into_buffer(packet)
- When the packet is at the top of the buffer, pass it onto the device at the other end and remove it from the buffer using
remove_from_buffer(packet)
- When the packet is at the top of the buffer, pass it onto the device at the other end and remove it from the buffer using
- If there isn't any room, drop the packet
- If there is any room in the buffer, add the packet to the buffer using
After waiting for start
, call source.start_flow(data, destination, tcp_type)
While there is a flow running, wait for interval
and for each router
in devices
, call router.send_router()