EECS 489 Lab 7: Rate Control with Token Bucket Filter
This assignment is due on Friday,
8 April 2016, 6 pm.
We 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
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 Sizing
The 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
2.852 tokens in your token bucket to send a single segment. To simplify
token accounting, we'll size the token bucket filter in unit of bytes
instead of tokens. Thus you can transmit the packet with 1460 bytes of
data if your token bucket filter contains that many bytes. 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 bytes/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 Transmission
Your 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 bytes 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 bytes in your
token-bucket filter to cover the segment. If there isn't enough
bytes, put the process to sleep. The amount of time the process
sleeps should be long enough to generate at least the number of bytes
needed to cover a single segment. Preferrably, it should sleep a
little longer than the minimum, to allow for more bytes 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, the support
code has usleep() redefined to call Sleep() in
netimg.h. In this assignment, to simplify the code, we don't
accumulate token during packet transmission time. Be sure to enforce
that the amount of bytes accumulated is not larger than
imgdb::bsize. Upon transmission of a segment, deduct the
bytes used from the amount of accumulated.
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 Code
Given 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:
% netimg -s localhost:<port> -q BlueMarble2004-08.tga -r 256
should take roughly twice as long to complete as
% netimg -s localhost:<port> -q BlueMarble2004-08.tga -r 512
and about three to four times as long as
% netimg -s localhost:<port> -q BlueMarble2004-08.tga -w 40 -r 1024
When connecting to CAEN from home over slow ADSL, I found that
% netimg -w 10 -r 10 -m 10248
works for most images, just be prepared to wait 5 to 20 minutes
for the image to be displayed (and your mileage may vary).
To 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 submission must compile and run without errors on CAEN
eecs489 hosts using the provided Makefile, unmodified, without any additional libraries or
Your "Lab7 files" comprises your imgdb.cpp.
To turn in your Lab7, upload a zipped
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
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.