CSE 473S FAQ, Fall 2007

Assignment 4 (last updated: Nov 28, 5.30 pm)

Some guidelines follow. Refer to Dr. Wong's lecture slides for detailed instructions/ screenshots.

  1. Though it's been mentioned in the class repeatedly, it's very easy to forget that the drop list is of pkt COUNTS and NOT pkt sequence numbers. If you miss this, the trace (on the receiver side) or thruput numbers will NOT make sense.

  2. When creating config B:
       
    Make sure to add a GM filter.

  3. Remember that you can send a command to the discard plugin to reset counters without resorting to the "crude" way. The crude way is to delete the (plugin) instance, unload the class, and the add the instance again.

  4. Remember that to run the plugin in debug mode, you need to do "make clean" and "make debug". Recreate the plugin instance as described in the previous bullet. In addition, you need to turn on debugging in RLI, and then look at debug.log (if you are using the default file name in RLI) on the CP.

  5. When you are in config C, you can omit "-x" in the cmd line arg to rcvr2. The reason should be obvious; if not, contact me. Also, you can use a lower number with -x (for instance, -x 50 etc.) during debugging.
     

  6. READMEs are there for a reason and so pls read them!

Assignment 3 (last updated: Nov 13, 8.30 am)

(Some answers here include responses from Prof. Gorinsky.)

 

1.      How can my program be both a client and a server at the same time?

When you launch your program on a node (n1p1a etc), check to see if you need to send out DV updates; if so, send; if not, wait for DV pkts from your neighbors. It is in this sense that you are acting both as client (while sending out) and as server (while awaiting DV pkts). There are of course details to take care of.

 

2.      I have a question about the start of the packet synchronization. In "Reliable delivery of distance vectors", the specifications says that a node communicates only one distance vector at a time by sending a single packet to a neighbor. At the beginning of the simulation, however, if all nodes send their forwarding vector and waits for the ACK packet, I think that it will not end, doesn't it? For example,

Node A send packet to Node B and wait for response.

Node B send packet to Node C and wait for response.

Node C send packet to Node A and wait for response.

Do I need to separate the receiving forwarding packet part and sending forwarding packet by using Multi-thread or Multi-process? Or does the first node starts sending packet to its neighbor, and the simulation starts?

Using more than one socket may address the scenario, without a need for multiple threads or multiple processes.

Hint: while you are waiting for an ack [using "select()"], if you receive a DV packet from a neighbor [using "select()" again], think about whether you still need to wait for the ack.

 

3.      I am a little confused on what it means to "incorporate delay plugins allowing the experimenter to modify end-to-end delays of overlay paths". Should we arbitrarily choose delays? Do we need multiple delay plugins at every port?

In your experiments, you can configure the inserted delay plugins to arbitrary delays so that you can see two different convergence patterns. Do remember to include the delay settings in your report so that we will be able to reproduce your results.

No, you do not need 2 delay plugins at the same port to have 2 delay values. Run the experiment with one value first and document the convergence pattern and then change the delay plugin value and document the second convergence pattern. Be sure to include the delay plugin value, each time, in your documentation. Note that without a delay plugin, pkts would be delivered almost instantaneously in ONL.

 

4.      And universal connectivity means that each node has a direct path with each other but only send info to their neighbors, right?

Correct. We want the universal physical connectivity so that no matter which overlay topology we specify (through the inputs provided to the nodes), the nodes are always connected to their neighbors.

You can get universal physical connectivity by using "Generate default routes" menu in ONL's RLI.

 

5.      I understand that the updates are sent to the immediate neighbors, my confusion was the path that should be used, should we route the updates through the calculated shortest path or should we just send straight to the host?  For example, if n1p2 were to send an update to its neighbor n1p1a and it had already calculated the direct cost from n1p2 to n1p1a as 7 and the cost through n1p3 as 5 would it send the update directly to n1p1a or through n1p3?

Use the link costs to generate the DV pkts (roughly speaking) but NOT for actually transmitting the pkts. The latter is handled by the universal connectivity in ONL.

 

1.      Simple code (in C) to read a line from a file is below. Modify it as you deem fit.

int fgetline(FILE *fp, char *buf, int buflen)

{

  int ch;

  int i;

 

  i = 0;

  ch = getc(fp);

  while ((ch != '\n') && (ch != EOF))

  {

    buf = realloc(buf, ++i);

    buf[i - 1] = (char)ch;

    ch = fgetc(fp);

  }

  buf = realloc(buf, ++i);

  buf[i - 1] = 0;

 

  return i - 1;

}

 

To use it, something like:

   // char *file : contains file name

   FILE *fp;

   if ((fp = fopen(file, "r")) != NULL)

   {

       // process the contents of the line as per your design

   }

   else

   {

       fprintf(stderr, "ERROR: Unable to open %s\n", file);

   }

2.       

ANNOUNCEMENT:

 

An ONL bug was discovered during assignment 2 where ONL did not transmit UDP pkts of payload lengths <= 12 bytes.

 

Here is an update from Dr. Wong told on that:

"The 12-byte bug has been fixed, and I just tested using both iperf and a modified version of pkt-pair.   I tried a variety of UDP payload lengths ranging from 1 byte to 12 bytes with no problem.

 

Assignment 2

-->> New questions or comments are added to the END of the list for assignment 2 <<--

 

1.      Assignment handout says "Log in from onlusr into n1p3 (through its onlXX.arl.wustl.edu address), install and run your server program" - how do I install my program?

Use scp or SSH client’s file transfer GUI utility to copy over your files to onlusr. The files are mounted across onlXX machines.

Example: scp myclient.c username@onl.arl.wustl.edu:/users/username/.

 

2.      How do I compile a C++ program, along with a .h file?

Example: g++-o myserver myserver.c

If you have a .h file, g++-o myserver stdinc.h myserver.c

If it’s C, you can use gcc.

 

3.      Is there a sample program that I can start with for socket programming?

Assuming that you are considering to code in C/ C++:

 

The code that Dr. Wong discussed in the class is at ~kenw/src/pkt-pair/*.c,*.h.

The path and the commands to run them are on slides 5 and 6 of his 2nd lecture (http://arl.wustl.edu/~kenw/courses/cse473s/current/wustl-473-f07-2.pdf).

Of course, he is doing pkt-pair which is different from assignment 2 but the code gives a good starting point for socket programming. Note that his stdinc.h has a function called HasMsg() that waits for an ack and if one is not received, times out. Just call it appropriately and handle the return value appropriately.

 

The key here is to develop incrementally, with the overall picture in mind. Roughly speaking, you can consider the following logical increments. First, keep

RTT fixed and send 1 pkt and receive its ack. Then, send 3 times the number of packets per every new ack. After that deal with 1st loss (timeout, dup ack).

Finally, make RTT dynamic and revisit all the previous steps.

 

If you are planning to start with Dr. Wong’s packet-pair code, here is a plan of development suggested by Dr. Wong. Note that this is just a suggestion meaning that you do NOT have to follow it necessarily.

 

v0 Stop-and-wait with timestamps

- insert sleep(2) in receiver code to slow things down and

-- do debugging with sndr and rcvr on localhost

- timeout = 3 sec

- '-n 4' pkts and '-n 9' pkts

- comment out call to pkt logging and stats

- use fixed RTO (Retransmission TimeOut)

- new command-line args: -l pktlen

- update command-line args: -n npkts to mean #pkts to send

- delete command-line args: -m nruns

 

v1 Slow start with fixed RTO

- in-order accept receiver

- exit on timeout; i.e., first pkt drop

- W = 1 on timeout

- receiver purposely drop certain pkts once

 

v2 Dynamic RTO

- do work on onl

- delete sleep(2) and deterministic dropping from receiver

- compute RTT

- vary RTO

- log pkt start times

 

Reference books for socket programming: "TCP/IP Sockets in C: Practical Guide for Programmers" by Michael J. Donahoo is a good reference. It's small and to the point.
Other references:
Beej's guide to network programming
Packet Formats from Network Sorcery

 

4.      If current window size is 3, client will send 3 messages in this round and server will return ACKs one by one. Does the client send 3 more packets after receiving the very first ACK (i.e.) without waiting for the other 2 ACKs?

Yes but observe that W = W + 2 for each new ack gives the desired effect of tripling the #pkts in flight when tripling the window (per RTT) (Courtesy: Dr. Wong).

 

5.      If current window size is 3, do we start the retransmission timer after sending the first of these 3 packets or AFTER sending all 3 packets?

Assignment handout says

Upon receiving an in-order ACK, the client transmits three new messages (i.e., W = W+2), calculates round-trip time T of the message-ACK pair as the difference between current time and the time stamp returned by the ACK, updates retransmission timeout X, and restarts the retransmission timer.

(i.e.) start the timer AFTER sending the 3 packets.

 

6.      Save the ONL project config in a file so that you don't need to recreate it every time. And every time you reload the config file, be sure to reconfigure the delay plugin to 800 msec (or else it reverts to the default of 50 msec).

 

7.      Do I need to worry about network-byte-ordering given that the architecture is the same on both the sender and receiver side?

You don’t need to worry about it for the reason you are stating. You can deal with it at the very end if you prefer.

 

8.      Are the 25,000 messages the time stamp and the sequence number themselves, or is there suppose to be anything else in the message like a phrase? I mean, we have to send 1kb packets each time right? I can send messages, but how do I make it so that each message has 1000 bytes? Because, if the message is only the time stamp and sequence, won't it fall short of 1000 bytes? I am a little confused about that.

Create a buffer of 1000 Bytes for (each) packet payload, initialize each Byte to zero and then use only the bytes you need for sequence number, timestamp etc.

 

9.      Are we required to implement duplicate acks, or can we just rely on timeout? It does not say anything about duplicate acks on the assignment, but you mentioned it on your faq.

Assignment says that receiver ignores out-of-order messages and sender also ignores out-of-order and duplicate ACKs (if it receives any).

 

10.  After the 1st packet loss, select() times out and keeps timing out forever. The server sends a new ack, but the client never sees it because select() times out and the timeout value never increases.

man select shows (paraphrased here)

"On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. This causes problems when code reuses the variable for timeout (struct timeval) in a loop without reinitializing it. Consider timeout to be undefined after select() returns."

 

11.   

12.   

 

 

Assignment 1

1.      (lab1 configuration) How do we count the #hops from n1p1b to n1p3 when there is no external link in NSP1?

We will learn later about how to do this. For now, just count the #links. So, where there is no external link in the router, there are 2 hops and when there is an external link, there are 3 hops.

 

2.      (lab1 configuration) Looking at an 6-7 external link in RLI, is it possible to say whether it is 6->7 or 7->6? Does it depend on from where to where you drag the link in RLI?

Well, links are bi-directional in ONL.

 

3.      (lab1 configuration) If we look at link bandwidth (in Queue table), the values are different for 6-> and 7->6. What does it mean?

The link bandwidth is the egress link bandwidth of the link at the port.

 

4.      (lab1 configuration) RLI shows an output link bandwidth at port 4. What does that refer to? This is what we see when we click on port 4 => config menu item "Queue tables" and look at the "Link bandwidth" textbox value.

From Prof. Wong:

The details of this will be discussed in ONL Lecture #2.   But the short answer for now is that is the maximum rate at which traffic is allowd to leave Port 4.   Details to be covered in Lecture #2:

o The rate is based on the IP pkt size (doesn't include ATM headers but does include IP and transport headers).

o The actual rate is allocated as a multiple of 54 Kbps. The effect of this shows up after commit is done.

o The rate is implemented as a token bucket with a depth of 2000 bytes. So, it is a work conserving rate regulator, NOT a rate emulator. This bullet is irrelevant for Lab 1.

 

5.      (lab1 configuration) What exactly is the bitrate displayed in “Display0” " panel, with "Bitrate from link 5-4" plot?

From Prof. Wong:

Link bandwidth at port 4:

This display was probably created from "Port 4 => Monitoring => Ingress => Port Bandwidth".

Clicking the label "Bitrate from link 5-4" shows:

NSP1:port4

Input port 4

Input port cell count/sec

...

This is one of those monitoring points that are actually inside the ATM switch fabric.   So, the data is generated by observing traffic coming from the FPX at Port 4 going into Port 4 of the ATM switch.   By inference, this is the traffic that entered Port 4 from Port 5; i.e., the traffic over the external link.

 

6.      (lab1 configuration) In the following iperf reports, what are the times shown in ms (at the server, at the client)?

------------------------------------------------------------

Server listening on UDP port 5001

Receiving 1470 byte datagrams

UDP buffer size:    108 KByte (default)

------------------------------------------------------------

[   4]   0.0-40.0 sec 2.60 MBytes 544 Kbits/sec 0.023 ms    19/ 1872 (1%)

 

------------------------------------------------------------

Client connecting to n1p3, UDP port 5001

Sending 1470 byte datagrams

UDP buffer size:    108 KByte (default)

------------------------------------------------------------

[   3] 0.0-40.0 sec 9.54 MBytes 2.00 Mbits/sec

[   3] Sent 6804 datagrams

[   3] Server Report:

[   3] 0.0-50.0 sec 4.58 MBytes 768 Kbits/sec 564.069 ms 3539/ 6804 (52%)

 

Answer:

Those times are the "jitter" values.

From http://dast.nlanr.net/Projects/Iperf/iperfdocs_1.7.0.php:

Jitter calculations are continuously computed by the server, as specified by RTP in RFC 1889. The client records a 64 bit second/microsecond timestamp in the packet. The server computes the relative transit time as (server's receive time- client's send time). The client's and server's clocks do not need to be synchronized; any difference is subtracted out in the jitter calculation. Jitter is the smoothed mean of differences between consecutive transit times.

 

7.