diff --git a/lab3/README.md b/lab3/README.md new file mode 100644 index 0000000000000000000000000000000000000000..63e280a2951741fd50a3a92e7dab89ec82c879f9 --- /dev/null +++ b/lab3/README.md @@ -0,0 +1,66 @@ +We have **two separate programs**, the sender and the receiver that use the implementation of our protocol. + +Normally, we would implement our protocol as a library, but to make things +easier, we implement part of the protocol in send.c, and the receving code in +recv.c. Note that we will use a Maximum Transmission Unit (MTU) of 1500. + +``send.c`` - the code that the sender will execute + +``recv.c`` - the code that the receiver on the other end of the wire will execute + +``common.h`` - header where we define the header of the protocol and other common functions. + +Overview of the architecture +``` + sender receiver + | | + data link data link + protocol protocol (used for framing) + | | + Physical layer Physical layer + protocol protocol + |______________________| + Physical (wire) +``` + +## C++ + +Note, if you want to use C++, simply change the extension of the `send.c` and +`recv.c` to `.cpp` and update the Makefile to use `g++`. + +## API +```C +/* This is the API exposed by the datalink protocol we're building upon and +already deals with framing. Our extension introduces the support for error +detection*/ +/* Send len bytes from buffer on the data link */ +int link_recv(void *buf, int len); +/* Receives a maximum of len bytes and writes it to buff */ +void link_send(void *buf, int len); + +/* The structure of our protocol */ +/* Layer 3 header */ +struct l3_msg_hdr { + uint16_t len; + uint32_t sum; +}; + +/* Layer 3 frame */ +struct l3_msg { + struct l3_msg_hdr hdr; + /* Data */ + /* MTU = 1500 */ + char payload[1500 - sizeof(l3_msg_hdr)]; +}; + +``` +## Usage +To compile the code +``` +make +``` + +We will run the sender and receiver in parallel using ``run_experiment.sh``. +This scripts first runs the receiver binary and then runs the sender binary. +Note that we use the `CORRUPTION` variable from the script to set the +corruption rate. diff --git a/lab3/common.c b/lab3/common.c index ad192ddff5b08b2ae7610dbcfe14aa15a8dbaa78..3830337a2ae8a08fc144039a454c5dd30a6d5f49 100644 --- a/lab3/common.c +++ b/lab3/common.c @@ -1,5 +1,20 @@ #include "common.h" -uint16_t inet_csum(uint8_t *buf, size_t len) { - //TODO1: Calculate the internet checksum according to RFC1071 +uint8_t simple_csum(uint8_t *buf, size_t len) { + + /* TODO 1.1: Implement the simple checksum algorithm */ + return 0; +} + +uint32_t crc32(uint8_t *buf, size_t len) +{ + /* TODO 2.1: Implement the CRC 32 algorithm */ + + /* Iterate through each byte of buff */ + + /* Iterate through each bit */ + /* If the bit is 1, compute the new reminder */ + + /* By convention, we negate the crc */ + return 0; } diff --git a/lab3/common.h b/lab3/common.h index fda4adc4dbaf89d9ec903042f243ad500bb07b6b..6a7af4affaa47d8d2c33c7612655439653806837 100644 --- a/lab3/common.h +++ b/lab3/common.h @@ -3,17 +3,20 @@ #include <stdbool.h> #include "link_emulator/lib.h" -uint16_t inet_csum(uint8_t *buf, size_t len); +uint8_t simple_csum(uint8_t *buf, size_t len); + +uint32_t crc32(uint8_t *buf, size_t len); /* Layer 3 header */ struct l3_msg_hdr { uint16_t len; - uint16_t sum; + uint32_t sum; }; /* Layer 3 frame */ struct l3_msg { struct l3_msg_hdr hdr; /* Data */ - char payload[sizeof(((msg *) NULL)->payload) / 2 - sizeof(struct l3_msg_hdr)]; + /* MTU = 1500 => we can send 1500 - header size bytes of data */ + char payload[1500 - sizeof(l3_msg_hdr)]; }; diff --git a/lab3/recv.c b/lab3/recv.c index 82481d1654fd6faec913d113972911e67cb57e43..b632832dd3589f2feace0f2689bcb2d02f7ccd99 100644 --- a/lab3/recv.c +++ b/lab3/recv.c @@ -9,39 +9,38 @@ #define HOST "127.0.0.1" #define PORT 10001 -static inline uint8_t hamming_7to4(uint8_t c) { - // TODO 3: Implement hamming decoding for one nibble - // TODO 4: Implement error correction -} - -size_t hamming_decode(uint8_t *enc, size_t len, uint8_t *buf) { - for (size_t idx = 0; idx < (len / 2); idx++) { - /* In the encoded message we have to concatenate 4 bits from two different bytes. */ - buf[idx] = hamming_7to4(enc[idx * 2]) << 4; - buf[idx] |= hamming_7to4(enc[idx * 2 + 1]); - } - - return len / 2; -} int main(int argc,char** argv) { - struct l3_msg t; + /* Don't modify this */ init(HOST,PORT); - uint8_t enc_ph[sizeof(struct l3_msg) * 2]; + struct l3_msg t; - /* Receive the encoded message */ - int len = link_recv(&enc_ph, sizeof(enc_ph)); + /* Receive the frame from the link */ + int len = link_recv(&t, sizeof(struct l3_msg)); if (len < 0){ perror("Receive message"); return -1; } - hamming_decode(enc_ph, len, (void *) &t); + int sum_ok = simple_csum((void *) t.payload, t.hdr.len) == t.hdr.sum; + /* TODO 2: Change to crc32 */ + + /* Since we are sending messages with a payload of 1500 - sizeof(header), most of the times the bytes from + * 30 - 1500 will be corrupted and thus when we are printing or string message "Hello world" we see no probems. + * This will be visible when we will be sending a file */ + + printf("[RECV] len=%d; sum(%s)=0x%04hx; payload=\"%s\";\n", t.hdr.len, sum_ok ? "GOOD" : "BAD", t.hdr.sum, t.payload); + + /* TODO 3.1: In a loop, recv a frame and check if the CRC is good */ + + /* TODO 3.2: If the crc is bad, send a NACK frame */ + + /* TODO 3.2: Otherwise, write the frame payload to a file recv.data */ + + /* TODO 3.3: Adjust the corruption rate */ - int sum_ok = inet_csum((void *) t.payload, t.hdr.len) == t.hdr.sum; - printf("len=%d; sum(%s)=0x%04hx; payload=\"%s\";\n", t.hdr.len, sum_ok ? "GOOD" : "BAD", t.hdr.sum, t.payload); return 0; } diff --git a/lab3/run_experiment.sh b/lab3/run_experiment.sh index c0e63ddfb86dccb2a5557d4e3bd07bede485cbeb..1aaeb90d2afed03e23a72d56b42a6b32b2af0889 100755 --- a/lab3/run_experiment.sh +++ b/lab3/run_experiment.sh @@ -3,7 +3,10 @@ SPEED=1 DELAY=1 LOSS=0 -CORRUPT=100 +# Adjust the corruption +CORRUPT=30 + +# Second bit corruption rate CORRUPT2=0 { diff --git a/lab3/send.c b/lab3/send.c index e20a610278fe0834721efb2be9174a25be16469c..0b6870cca72db5746da984a50e9aae0ddc0bb6c5 100644 --- a/lab3/send.c +++ b/lab3/send.c @@ -11,19 +11,6 @@ #define HOST "127.0.0.1" #define PORT 10000 -static inline uint8_t hamming_4to7(uint8_t c) { - // TODO 2: Implement hamming encoding for one nibble -} - -/* For each 4 bits we add 3 redundancy bits. We split a byte intwo two */ -size_t hamming_encode(uint8_t *buf, size_t len, uint8_t *enc) { - for (size_t idx = 0; idx < len; idx++) { - enc[idx * 2] = hamming_4to7(buf[idx] >> 4); - enc[idx * 2 + 1] = hamming_4to7(buf[idx] & 0xf); - } - - return len * 2; -} int main(int argc,char** argv) { init(HOST,PORT); @@ -34,15 +21,21 @@ int main(int argc,char** argv) { /* We set the payload */ sprintf(t.payload, "Hello World of PC"); t.hdr.len = strlen(t.payload) + 1; + /* Add the checksum */ - t.hdr.sum = inet_csum((void *) t.payload, t.hdr.len); + t.hdr.sum = simple_csum((void *) t.payload, t.hdr.len); - /* Encode the message with error correction codes */ - uint8_t enc[2 * (sizeof(t.hdr) + t.hdr.len)]; - hamming_encode((void *) &t, sizeof(enc) / 2, enc); + /* TODO 2.0: Call crc32 function */ /* Send the message */ - link_send(&enc, sizeof(enc)); + link_send(&t, sizeof(struct l3_msg)); + + /* TODO 3.1: Receive the confirmation */ + + /* TODO 3.2: If we received a NACK, retransmit the previous frame */ + + /* TODO 3.3: Update this to read the content of a file and send it as + * chunks of that file given a MTU of 1500 bytes */ return 0; }