首页 > > 详细

Assignment 3: Reliable Transport

 Assignment 3: Reliable Transport

1 Environment
To set up the environment for this assignment, you must follow the instructions from “assignment0”.
The instructions can be found at “ECE50863/assignment0/README.pdf”. Once the VM has booted
(by using the command “vagrant up”) and you have established a SSH connection (by using the
command “vagrant ssh”), you should enter the assignment directory by running the command “cd
assignment3”. Now you are ready to run the assignment!
2 Task
For this assignment, your task is to implement a reliable transport layer. We will call it tinytcp. Just
like real TCP, tinytcp should deliver a stream of bytes reliably and in-order to applications over the
network. To accomplish this, tinytcp should implement connection set up and termination, appli￾cation multiplexing, data acknowledgments and retransmissions, similar to TCP. However, unlike
TCP, tinytcp need not implement flow control and congestion control.
2.1 File transfer application
We run a simple file transfer application overtinytcp. Currently tinytcp only supports ASCII (.txt) file
transfers from a client to a server. You can assume that there will be a single client and a single server.
However, the client can initiate multiple (up to a maximum of 5) file transfers in parallel. Internally,
tinytcp would create multiple parallel streams (one for each file transfer) between the client and the
server. Your implementation should be capable of multiplexing between multiple tinytcp streams.
3 Building and Running the Code
tinytcp is a real system that can be used to transfer files reliably between any two machines over a
network. However, for the ease of testing, you will run both the client and the server on the same ma￾chine, connected over the loopback network interface (IP: 127.0.0.1, defined in “SERVADDR” parameter
in “tinytcp.c”). For remote testing, you would change “SERVADDR” value to the IP address of the
remote server (not required for this assignment). However, since there is not going to be any phys￾ical link(s) between the client and the server in our loopback network, we simulate the link inside
“tinytcp.c”. The link can be configured to be lossy as described below.
You should open up two SSH VM terminals (using the command “vagrant ssh”). In one terminal,
you will run the server and in the other terminal the client. First, compile the code by running “make”
in one of the terminals,
$ make
Next, to start the server, run the following command in one of the terminals,
$ ./bin/tinytcp server [loss_probability]
2
Here, “loss_probability” must be a number between 0 and 100. This value configures the proba￾bility with which a packet will be dropped/reordered over the simulated link. For example, if you
set the loss probability value to 0, no packets will be dropped/reordered over the simulated link.
Similarly, if you set the value to 100, all packets will be dropped. However, you can assume that the
connection set up and termination packets (SYN, SYN-ACK, ACK, FIN, FIN-ACK, ACK) are never dropped.
IMPORTANT: Always start the server before starting the client!
Finally, to start the client, run the following command in the other terminal,
$ ./bin/tinytcp client [loss_probability] [file1 file2 ...]
Here, “file1”, “file2” etc. are the filenames that you want to transfer. You can specify up to a max￾imum of 5 files. Also note that the loss probability values can be different for the client and the server.
Client’s loss probability value determines the probability with which packets sent by the client will
be dropped/reordered (similarly for the server).
IMPORTANT: All files that you want to transfer must be stored inside the “sendfiles/” directory.
We have already provided you with a set of files that you can use for testing. All the files received at
the server are stored inside the “recvfiles/” directory.
Debugging Tip: Each run of the code generates four .dump files inside the directory “dumps/”. These
files store the information about all the packets that were sent and received by the client and the server
during the run of the experiment. You can use these files to debug your implementation.
To clean the working directory, run the following command in one of the terminals,
$ make clean
This will clean all the unnecessary files, including the dump files and the received files from the last
run of the experiment.
4 Output
Figure 3 and Figure 4 show sample terminal outputs for the client and the server respectively. Note
that these outputs are for a fully implemented tinytcp. The output of a partially implemented tinytcp
might not show all the information.
In the sample output, client is sending three files in parallel. The loss probability is 20% on both the
client and the server side. The output shows the information about the connection set up and termi￾nation packets. In addition, the output also shows the progress of file transfer using the character “=”.
On the client side, the character “=” is printed every time a packet is sent to the network. On the server
side, character “=” is printed every time some data is wriĴen to the receiving file. You can use this to
make sure that your code is making progress. Note that it is normal for the client to print more “=”
characters than the server, since not all packets sent by the client will reach the server due to lossy link.
Once all the files have been transferred, the code will print the transfer statistics on the client terminal.
This includes the total time of transfer and the total bytes sent (including the ones that were dropped).
At the end, the code matches the received files against the corresponding sent files, and prints either
“SUCCESS” or “FAILURE” depending upon whether the sent and received files are identical or not.
5 Milestones and Grading
This assignment has four milestones, with 25% credit each. To get full credit, you must hit all four
milestones (75% if you hit first three, 50% if you hit first two, and 25% if you only hit first milestone).
3
5.1 Milestone 1: Connection set up and termination (25% credit)
For the first milestone, you should try to implement only the connection set up and termination part
of the code, without worrying about any actual file data transfer. You can use the “empty.txt” file
inside the “sendfiles/” directory to test this milestone. Example, once you have finished your im￾plementation, you can run the following commands in the terminal for testing,
$ ./bin/tinytcp client 0 empty.txt
$ ./bin/tinytcp server 0
The output should look similar to Figure 3 and Figure 4. You should also test your code with multiple
empty files.
5.2 Milestone 2: File transfer over a lossless link (25% credit)
For the second milestone, you must be able to successfully transfer files between the client and the
server. However, you can assume that the link is lossless, i.e., you can set the loss probability value
to 0 on both the client and the server side. Your code must be able to successfully transfer multiple
files in parallel.
5.3 Milestone 3: File transfer over a lossy link – Performance Agnostic (25% credit)
For the third milestone, you must be able to successfully transfer multiple files in parallel over a lossy
link. For starters, you can set the server side loss probability to 0, but eventually your code must
work with any loss probability value on both the client and the server side. Note that the focus of this
milestone is only on correctness, and not on performance. So you are free to implement even the most
naive reliability protocol, for example, send a single data packet and wait for an ACK until timeout.
If the ACK arrives before timeout, send the next packet in line, else retransmit the first packet.
5.4 Milestone 4: File transfer over a lossy link – Performance Aware (25% credit)
For the final milestone, you will need to implement Cumulative ACK with Go-Back-N, and retrans￾mit on receiving 3 Duplicate ACKs (Fast Retransmit) or timeout, whichever happens first. We will
test the performance of your implementation against our own implementation. To receive full credit,
both the total time taken for file transfer and the total bytes sent must be in the same ball-park as our
implementation.
IMPORTANT: The retransmission timeout value is already configured in the code provided to you
(RTO value in file “include/tinytcp.h”). You must not retransmit packets using some different time￾out value. This is to ensure that the performance comparison between your implementation and our
implementation is fair. Violation of this guideline can result in significant penalty!
6 Source Code
The source files for this assignment can be found inside the “src/” directory. You are provided with
three source files — “tinytcp.c”, “ring_buffer.c”, and “handle.c”. You will do all your implemen￾tation inside “handle.c”. You must not modify any other files. Further, “handle.c” file is tagged with
several TODO comments that guide you in the right direction in terms of what to implement. Read
those comments very carefully. You must not delete/modify any existing code inside “handle.c”.
Multiplex
handle_send_to_network()
send_to_network()
Thread 1
send
buffer
send
buffer
handle_close()
send_to_network()
tinytcp_connect()
send_to_network()
tinytcp_close_conn()
Multiplex
handle_recv_from_network()
recv_from_network()
Thread 2
recv
buffer
recv
buffer
send_to_network()
4
Figure 1: Workflow of tinytcp. Functions in red need to be implemented.
6.1 Workflow
To start a file transfer, the client side application first calls “tinytcp_create_conn()”. This cre￾ates a “tinytcp_conn_t” structure (defined in “include/tinytcp.h”). This structure stores all the
connection-specific information needed in tinytcp.
Next, the client calls “tinytcp_connect()” inside “handle.c”. This starts the 3-way handshake with
the server. It first sends a SYN packet, waits to receive a SYN-ACK packet, and finally sends an ACK
packet, and returns. After this function successfully returns, the connection is established. You are
supposed to implement tinytcp_connect().
tinytcp runs a separate thread for receiving and handling of the received packets. The receive thread
(“recv_from_network()” inside “tinytcp.c”) runs in an infinite loop, waiting to receive packets
from the network. On receiving a packet, it calls the “handle_recv_from_network()” function in￾side “handle.c”. You are supposed to implement handle_recv_from_network().
For file data transfer, the client side application periodically reads small chunks of data from the
specified file, and writes it to that particular connection’s send buffer. In case of multiple file transfer
connections, data is read concurrently into the respective send buffers. This is implemented inside
“tinytcp.c”. In a separate thread, tinytcp runs “handle_send_to_network()” function. This func￾tion arbitrates over all the active send buffers in an infinite loop, and chooses one send buffer at a
time in a round robin manner. It then sends some data from that buffer into the network (by calling
“create_tinytcp_pkt()” followed by “send_to_network()”, both implemented in “tinytcp.c”),
before moving to the next send buffer. You are supposed to implement handle_send_to_network().
On the server side, on receiving some data from the network, the “handle_recv_from_network()”
function inside “handle.c” writes the data into the corresponding connection’s receive buffer. The
server side application periodically reads data from all the active receive buffers, and writes it to the
respective files inside the “recvfiles/” directory.
Once the application has read the entire file on the client side, it calls “tinytcp_close_conn()” func￾tion inside “tinytcp.c”. This function changes the state of the connection to “READY_TO_TERMINATE”
and returns immediately. The “handle_send_to_network()” function inside “handle.c” on real￾izing that the connection is ready to terminate, waits till all the remaining data inside the connec-
SYN_SENT
SYN_ACK_RECVD
CONN_ESTABLISHED
READY_TO_TERMINATE
FIN_SENT
FIN_ACK_RECVD
CONN_TERMINATED
SYN_RECVD
SYN_ACK_SENT
CONN_ESTABLISHED
FIN_RECVD
FIN_ACK_SENT
CONN_TERMINATED
Client State Transitions Server State Transitions
Data
5
tion’s send buffer has been reliably transferred, and then initiates connection termination by calling
“handle_close()” function in “handle.c”. “handle_close()” function sends a FIN packet, waits to
receive a FIN-ACK packet, and finally sends an ACK packet and returns. After this function successfully
returns, the connection is terminated. You are supposed to implement handle_close().
Figure 2: State transitions in tinytcp.
6.2 Send and Receive Buffers
The send and receive buffers in tinytcp are instances of the ring buffer datastructure implemented in
“ring_buffer.c”. A ring buffer is a fixed-capacity First-In-First-Out (FIFO) queue. The ring buffer
has a head and a tail pointer. New data is always added at the tail of the ring buffer, and the tail
pointer is then moved to the end of the new data (“ring_buffer_add()” function). Similarly, data
is always removed (read) from the head of the ring buffer, and the head pointer is moved ahead by
the amount of data read (“ring_buffer_remove()” function). All the valid data inside a ring buffer
lies between the head and the tail pointers, and the ring buffer is considered empty if the head and
the tail pointers coincide. We provide you with the implementations of all the basic ring buffer
operations, but you might have to implement a few more functions for Cumulative ACKing and Go￾Back-N. If you need to implement any additional ring buffer functions, do it inside “handle.c” file.
6.3 State Machine
A tinytcp connection can be in one of 11 different states, as defined in enum “tinytcp_conn_state_t”
in “include/tinytcp.h” file. The state of a connection is configured using the “curr_state” vari￾able in “tinytcp_conn_t” structure. For your implementation, you will have to constantly transition
between different states. Below we describe the various state transitions in tinytcp. A tinytcp connection starts in an undefined state. Just before sending a SYN packet, the current state
changes to SYN_SENT. On receiving a SYN packet, the current state changes to SYN_RECVD. Just before
sending a SYN-ACK packet, the current state changes to SYN_ACK_SENT. On receiving a SYN-ACK packet,
the current state changes to SYN_ACK_RECVD. Just before sending the ACK packet in connection set up,
6
the current state changes to CONN_ESTABLISHED. Similarly, on receiving an ACK packet in connection
set up, the current state changes to CONN_ESTABLISHED.
All file data transfers happen when both the client and the server side connections in tinytcp are in
the CONN_ESTABLISHED state.
Once the client has read the entire file, it changes the current connection state from CONN_ESTABLISHED
to READY_TO_TERMINATE.
Just before sending a FIN packet, the current state changes to FIN_SENT. On receiving a FIN packet, the
current state changes to FIN_RECVD. Just before sending a FIN-ACK packet, the current state changes to
FIN_ACK_SENT. On receiving a FIN-ACK packet, the current state changes to FIN_ACK_RECVD. Just before
sending the ACK packet in connection termination, the current state changes to CONN_TERMINATED. Sim￾ilarly, on receiving an ACK packet in connection termination, the state changes to CONN_TERMINATED.
7 Submission
You are required to submit a single file “handle.c” on Brightspace.
7
Figure 3: A sample client side output.
8
Figure 4: A sample server side output.
联系我们
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 99515681 微信:codinghelp
程序辅导网!