Lab 09: Working with CRC

Goals

Credits

The materials in this lab come from various sources, including textbooks and websites. A partial list of textbooks that contribute to the ideas in the lab include our textbook Computer Networking: A top-down approach by Kurose and Ross, Computer Networks by Tanenbaum, and Computer Networks by Peterson and Davie. The code for CRC Model comes from the paper and discussion by Ross Williams on the subject.

Checking for Errors in Transmitted Data

In our last week's lab, we used a client (source) program to send a piece of data to a gateway before reaching the final receiver (sink). The sink in turn sends back the data to the source. The gateway could randomly alter the data so that the data sent from the source may be different when the source receives back from the sink. The lab assignment asked the source to check if the data received from the sink is the same as the one sent out.

In a real world application, a sender typically can't ask the receiver to send back the data to check to see if the data was sent correctly. Rather it is the responsibility of the receiver to check for data integrity. One possible, and effective mechanism is to use a checksum to examine to see if the data received contains errors or not.

The basic idea of a checksum is for the sender to compute a checksum value using certain algorithms. The checksum is then sent along with the data. When receiving the data along with the checksum, the receiver performs a checksum computation to see if the data has been altered. The simplest mechanism is a parity check, one that computes the number of one bit (or zero bit), the checksum bit is then added to the data to make either an odd parity or even parity check. A more elaborate and effective checksum mechanism is Cyclic Redundancy Checksum which is based on some algebra theory. That is, if the remainder R(x) results from D(x)/G(x), where D(x) is an n bit data, G(x) is an r+1 bit generating function, and R(x) is an r bit sequence, then the data sequence D(x) with R(x) attached to the end, effectively S(x) = D(x)*2^r+R(x) will be received by the receiver. When the receiver performs the same division operation S(x)/G(x), the remainder should be 0. If the remainder is not a zero, the data received contains error(s).

CRC Checksum Computation

While the basic idea of CRC as a checksum is not very complicated, the implementation of CRC in any programming language does involve many engineering challenges, mainly because CRC may not always be at the boundary of a byte and the fact that one has to shift through each bit of the data to compute CRC. You will find many CRC computation related discussions and solutions on the web. Here we will use one of the well-known solution by Ross Williams.

Your Tasks

In last week's lab, you created programs source.c, sink.c and gateway.c. In this lab, you will revise the programs so that the source sends a message of certain length with a CRC to the gateway, which in turn forwards data to the sink. The sink will be responsible for checking the errors in the message using CRC. The gateway can randomly alter the message with certain probability (just like we did in last lab.) If the sink finds that the message is in error by computing the checksum, the sink simply reports the problem to its screen (i.e., no error correction or retransmission is involved in this lab.)

We list the tasks as multiple problems to help you solve the problem in pieces. You could do it in one step if you feel comfortable about your solution.

Set up

Copy all files from ~cs363/Spring13/student/labs/lab09/* You should see a set of six files. The use of these files will become clear as you work through the lab.

Problem 1: Revise the source/gateway/sink programs

Rewrite the trio source.c, gateway.c and sink.c so that the message is sent from the source to the sink, via the gateway. The sink doesn't need to echo back the message.

The invocation of the programs may look as follows.

In this part of the lab, no error checking is used, though you could have the sink to print the message, or the length of the message, or both to indicate the programs are working fine.

Problem 2: Reading and sending file contents

Revise the source.c so that instead of just creating a message of certain length, the source opens a file from the name given at the command line using the system call open and send the content of the file to the gateway. The general strategy is as follows.

You can try the program with any files, text or non-text. You can certainly try your programs on the files that you copied from the lab directory, Declaration of Independence, or Lincoln's Gettysburg Address.

Problem 3: Incorporating CRC into the message

As mentioned before, implementing a CRC program can be involved. We will use Ross Williams's solution in our lab. Read a bit the paper by Ross Williams at the following website. Do not spend too much time. The point here is to give you a sense that computing a generic CRC is not a very simple engineering task.
http://www.ross.net/crc/crcpaper.html

Next read a bit more the file crcmodel.h, especially, the section "How to Use This Package" where Williams discussed how to set up and use the program. I've created a program crctest.c following Williams's instruction. You can simply do the following to try it out.

make
./crctest

You can revise the program by uncommenting Line 90 in crctest.c to test the case when the message is altered.

Your task is then to create a function that your program could call from source when a message is prepared to be sent to the gateway. The program interface for this function should look something like this.

unsigned int generate_crc(char * text, int len)

where the text parameter is the data for which you try to generate the CRC, len is the length of the data. Note that though we use char * as the type for the text, the data could be binary. Thus a separate variable len is needed because we can't rely on the likes of strlen() to compute the length of the data for us. The function returns the computed CRC that can be used by the calling function.

It might be the easiest if you simply rename the file crctest.c to be something like crc-api.c and revise the main() function such that it conforms the specification of generate_crc(). You will need to remove unnecessary activities in the current main() function. In particular, the setup() function needs to be called before every use of the CRC Model. In the current main() function, the setup() function is called twice because we compute CRC twice in the main() function. Your generate_crc() need to call the function setup() only once.

Once the generate_crc() is written, you need to call it within the source.c right before sending the message to the gateway. As a matter of fact, you need to generate the CRC for the message and attach the generated CRC as a part of the message (trailer). How do we attach the CRC to the end of data (an array of bytes)? One way to accomplish the task is to allocate extra r bytes for the message buffer. Assume the length of the text to be sent is n. Then you'd need to allocate n+r bytes, where the first n bytes are for the data and the last r bytes are for the CRC. Once the data is read into the buffer, you can attach the CRC to the end of the data by the following mechanism.

memcpy(&(buffer[n]), &crc, length_of_crc) where length_of_crc should be r.

Your next task is to revise the sink.c so that the sink will determine if the data is correct by computing the checksum that comes with the data. If the data is not corrupted, the checksum now should be zero. If a non-zero checksum is the result of the computation, an error exists. The sink should report it to its screen. (Again, no correction or retransmission is involved.)

Test your programs as you develop. Create an answer.txt to record a session or two in which both successful transmission of data without error(s) and cases when error(s) are detected. One of the tests should include the Lincoln's Gettysburg Address. Print the checksum for the text. You can use copy-and-paste mechanism, or some screen capture program such as script to record your sessions. Please do not include graphics-based screen-capture result. Also in the answer.txt please give the instructions how to compile and run your programs.

When you're done with the lab problem, make sure you remove unnecessary files, then submit the work to Gitlab.

Congratulations! You just finished this lab.