EECS 489 Lab 7: Rate Control with Token Bucket FilterThis assignment is due on Friday, 8 April 2016, 6 pm.
IntroductionWe have seen how sliding window flow control allows the receiver to throttle sender's transmission so as not to overflow the receiver's buffer. By relying on returning ACKs to slide the sender's window forward, sliding window flow control is a close-loop system. In this lab we investigate the use of open-loop sender rate control. The advantage of open-loop control is obviously that we don't have to wait one round-trip time for ACK packets to drive sender transmission. Instead, the receiver specifies a token-bucket filter that governs how bursty and how fast, on average, the sender can transmit. Since rate control by itself does not provide reliability, packets can still be dropped or arrive out of order. We start with a UDP-based client-server code with no flow control nor reliability, very similar to the client in Lab5. The only difference is that the client takes an additional command line argument, -r, which is used to specify the flow rate, in Kbps. (The reason the flow rate is specified at the client side instead of the sender side will become apparent in Lab8. Flow rate 0 is used in PA4.) You are provided with the full client source code, so no client reference binary is provided. A reference Linux binary executable of the server refimgdb is available in /afs/umich.edu/class/eecs489/w16/lab7/ where you can also find a tarball of the support code. The provided Makefile builds both netimg and imgdb. The two tasks you're asked to do in this lab are both server tasks. Your implementation of the server must interoperate with the provided client code. Since the provided client code reveals partial solution to Lab5 and PA3, you will be granted access only after you're done with your PA3 or have decided not to complete it.. As usual, you can search for the string "YOUR CODE HERE" in the code to find places where your code must go. You may also want to consult the PA4 walk-through lecture notes.
Task 1: Token-Bucket Filter SizingThe imgdb server in this lab does not take any command line option. The image file the client queries must reside in the same folder from which the server is launched. In imgdb::handleqry(), the flow rate specified in the client's query packet is stored in imgdb::frate for you. Your first task is to compute, in imgdb::handleqry() the token bucket size and token generation rate to regulate the sender's transmission. The token bucket size should be large enough to hold at least as many tokens as are needed to cover one mss segment, excluding all headers. If the receiver's window, rwnd, is larger than 1 mss, the token bucket size should be sized such that the server can fill the receiver's window, but no larger. You may find the macro IMGDB_BPTOK, defined in imgdb.h, useful in doing this computation. This macro specifies the number of bytes corresponding to a single token. For example, if your mss is 1460 bytes and IMGDB_BPTOK is 512 bytes, you'll need to have 3 tokens in your token bucket to send a single segment (or less if we allow for fractional token, as we do below). To ensure transmission progress, your token bucket must be sized large enough to hold at least the number of tokens needed to send a single segment. Next compute the token generation rate, which is simply a translation of the user-specified sender's rate from Kbps to tokens/sec. Store the computed token-bucket size in imgdb::bsize and the token rate in imgdb::trate. You can search for the string "Task 1" in imgdb.cpp to find the one place to enter your 3 lines of code for sizing the token-bucket filter. And that's all you have to do for Task 1.
Task 2: Rate-controlled TransmissionYour second task is to regulate the server's transmission rate. You can search for the string "Task 2" in imgdb.cpp to find the two places in imgdb::sendimg() where "Task 2" related code must be filled in. First, decide what local variables you would need to regulate packet transmission using the token bucket filter. Initialize your local variables. Regulate only the transmission of NETIMG_DATA packets. For a segment to be transmitted, there must be enough tokens in the token bucket filter to cover the data portion of the packet, i.e., mss minus all headers. To send a segment, you first check if there's enough tokens in your token-bucket filter to cover the segment. If there isn't enough tokens, put the process to sleep. The amount of time the process sleeps should be long enough to generate at least the number of tokens needed to cover a single segment. Preferrably, it should sleep a little longer than the minimum, to allow for more tokens to accumulate. For example, you could sleep for an additional amount of time sufficient to cover a random fraction of the token bucket size. On Linux and Mac OS X, use usleep() instead of sleep() to get microseconds granularity sleep time. On Windows, we've redefined usleep() to call Sleep() in netimg.h. In this assignment, we assume that the time to transmit a bucket-full of data is negligible, compared to the time needed to generate a token, given the token generation rate. If the transmission time of a bucket-full of data is not negligible, we'd need to account for the tokens generated during that time also (which we won't do). In any case, be sure to enforce that the amount of token accumulated is not larger than imgdb::bsize. Upon transmission of a segment, deduct the token(s) used from the amount of accumulated tokens. Token consumption can be fractional. For example, instead of using 3 tokens to send a segment of size 1460 bytes, you can use 2.85 tokens. The same applies to token generation: you can generate fractional tokens. That's is for Task 2. It should take about 12 lines of code. That's right, this whole assignment takes only about 15 lines of code in total.
Testing Your CodeGiven appropriate receiver window size (-w) and sender's flow rate (-r), you should be able to specify a token bucket filter that allows you to transfer an image file without overflowing the receiver buffer and therefore can be displayed with no gap in the image, modulo dropped packets. A larger receiver window means that the sender can send a large burst at once. So unlike in previous assignments, a larger receiver window does not necessary result in reliable transfer with no dropped packets. A smaller sender's rate not only slows down transmission, it also slows down the token (re)generation rate. For example, on localhost, with the default receiver window of 10 packets and mss of 3KB:
Submission InstructionsTo incorporate publicly available code in your solution, or to pass off the implementation of an algorithm as that of another are both considered cheating in this course. If you can not implement a required algorithm, you must inform the teaching staff when turning in your assignment. Your submission must compile and run without errors on CAEN eecs489 hosts using the provided Makefile, unmodified, without any additional libraries or compiler options. Your "Lab7 files" comprises your imgdb.cpp.
To turn in your Lab7, upload a zipped or gzipped tarball of your Lab7 files to the CTools Drop Box. Keep your own backup copy! The timestamp on your uploaded file is your time of submission. If this is past the deadline, your submission will be considered late. You are allowed multiple "submissions" without late-policy implications as long as you respect the deadline. We highly recommend that you use a private third party repository such as github or M+Box or Dropbox or Google Drive to keep the back up copy of your submission. Local timestamps can be easily altered and cannot be used to establish your files' last modification times (-10 points). Be careful to use only third-party repository that allows for private access. To put your code in publicly accessible third-party repository is an Honor Code violation.Turn in ONLY the files you have modified. Do not turn in support code we provided that you haven't modified (-4 points). Do not turn in any binary files (object, executable, dll, library, or image files) with your assignment (-4 points). Your code must not require other additional libraries or header files other than the ones listed in the Makefile (-10 points).
Do remove all printf()'s or cout's and cerr's and any other logging statements you've added for debugging purposes. You should debug using a debugger, not with printf()'s. If we can't understand the output of your code, you will get zero point.