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 thelinkthe 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 tolinksreceive_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_tablein aRouterPacketto all neighborsreceive_router(RoutingPacket -> (neighbor_distance_table, link, buff_occ)):- For each
deviceinneighbor_distance_table:
- If
deviceis not inrouting_table, updaterouting_tableanddistance_tablewithlinkandneighbor_distance_table[device] - If
routing_table[device] == link(i.e. we already use this link to get todevice), updatedistance_tableusingneighbor_distance_tableandbuff_occ - If
neighbor_distance_table[device] + buff_occ < distance_table[device](i.e. there is a new, better path), then updaterouting_tableanddistance_tableto include this
- If
routing_tablehas 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 todestinationif there is anydataleft 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.smallestandfast_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 todestinationif there is anydataleft to send
- Initializes
-
update_rtt(send_time, arrival_time): updatefast_RTTbased 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_idis not inreceived- Add it to
received - Get
next_id = get_next_ack() - Call
send_ack(next_id, DataPacket.source)
- Add it to
- If
p_idis 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): adddevicetodevicesinsert_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()