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;
 }