Skip to content
Snippets Groups Projects
Commit eda7d00d authored by Vlad-Andrei BĂDOIU (78692)'s avatar Vlad-Andrei BĂDOIU (78692)
Browse files

lab3: Update the skeleton to use CRC

parent e34b3151
Branches master
No related tags found
No related merge requests found
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.
#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;
}
......@@ -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)];
};
......@@ -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;
}
......@@ -3,7 +3,10 @@
SPEED=1
DELAY=1
LOSS=0
CORRUPT=100
# Adjust the corruption
CORRUPT=30
# Second bit corruption rate
CORRUPT2=0
{
......
......@@ -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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment