Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pcom/pcom-laboratoare-public
  • alexandra.girnita/pcom-laboratoare-public
  • clara_maria.ciarnau/pcom-laboratoare-public
  • gabriela.limberea/pcom-laboratoare-public
  • tudor.cornescu/pcom-laboratoare-public
  • ioana.iordache0506/pcom-laboratoare-public
  • alexandru.vasile03/pcom-laboratoare-public
  • flavius.mazilu/pcom-laboratoare-public
  • robert.teodorescu03/pcom-laboratoare-public
  • alexandru.barbu2809/pcom-laboratoare-public
  • teodor_adrian.miron/pcom-laboratoare-public
11 results
Show changes
Commits on Source (21)
......@@ -306,20 +306,20 @@ void *run_forwarding(void *param)
if (rand() % 100 < corrupt2) {
// flip a second bit in the same byte
int random_bit2;
do {
random_bit2 = rand();
} while (random_bit2 == random_bit);
int random_bit2 = rand();
if(random_bit % 8 == random_bit2 % 8) {
random_bit2 += 1;
}
m->payload[random_byte] ^=
1 << (random_bit2 % 8);
}
// printf("Enqueue 1.");
pthread_mutex_lock(&buffer_lock);
enqueue(buffer, m);
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_lock);
// printf("Done!\n");
}
// printf("Enqueue 1.");
pthread_mutex_lock(&buffer_lock);
enqueue(buffer, m);
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_lock);
// printf("Done!\n");
}
}
}
......
File moved
File deleted
File deleted
......@@ -21,11 +21,7 @@ client: client.c include/utils.h lib/queue.o lib/list.o
# Construieste un fisier de 1MB (1024B*10^4)==1MB
random_file:
dd if=/dev/urandom of=file.bin bs=1024 count=100
run_benchmark: server client
./server &
./client
dd if=/dev/urandom of=file.bin bs=1024 count=1000
clean:
rm -f server client file.bin received_file.bin *.o include/*.h.gch
......@@ -14,7 +14,7 @@ Topology:
client <--> router <--> server
Link 1 - 10 Mbps, 5ms delay, 0% packet loss (parameters set at topo.py:57)
Link 2 - 10 Mbps, 5ms delay, 0% packet loss (parameters set at topo.py:60)a
Link 2 - 10 Mbps, 5ms delay, 0% packet loss (parameters set at topo.py:60)
client IP (h1) - 192.168.1.100
......@@ -37,6 +37,8 @@ t = queue_deq(datagram_queue)
Our protocol implementation will have the following datagram structure over UDP:
```C
#define MAXSIZE 1024
struct seq_udp {
uint32_t len;
char payload[MAXSIZE];
......@@ -60,7 +62,7 @@ the server from `h2`.
To run a benchmark, use:
```bash
make run_benchmark
sudo python3 topo.py benchmark
```
## C++
......
......@@ -110,7 +110,7 @@ void send_a_message(int sockfd, struct sockaddr_in server_address) {
rc = recvfrom(sockfd, &ack, sizeof(ack), 0, NULL, NULL);
}
int main(int argc, char *argv[]) {
int main(void) {
/* We use this structure to store the server info. IP address and Port.
* This will be written by the UDP implementation into the header */
......@@ -132,7 +132,8 @@ int main(int argc, char *argv[]) {
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
inet_aton(SERVER_IP, &servaddr.sin_addr);
rc = inet_aton(SERVER_IP, &servaddr.sin_addr);
DIE(rc == 0, "Invalid IP address for server");
/* TODO: Read the demo function.
Implement and test (one at a time) each of the proposed versions for sending a
......
......@@ -24,6 +24,7 @@ void recv_seq_udp(int sockfd, struct seq_udp *seq_packet) {
/* Receive the contents of the file */
int rc = recvfrom(sockfd, seq_packet, sizeof(struct seq_udp), 0,
(struct sockaddr *)&client_addr, &clen);
DIE(rc < 0, "recvfrom");
int ack = 0;
// Sending ACK. We model ACK as datagrams with only an int of value 0.
......@@ -72,7 +73,7 @@ void recv_a_message(int sockfd) {
DIE(rc < 0, "send");
}
int main(int argc, char *argv[]) {
int main(void) {
int sockfd;
struct sockaddr_in servaddr;
......
......@@ -21,6 +21,7 @@ from mininet.node import Node
from mininet.log import setLogLevel, info
from mininet.cli import CLI
from mininet.link import TCLink
import time
import sys
class LinuxRouter( Node ):
......@@ -68,11 +69,13 @@ class NetworkManager(object):
def run_benchmark(self):
server = self.h2.popen("./server", shell=True)
# Give server some time to start
time.sleep(1)
client = self.h1.popen("./client", shell=True)
server.wait()
print("##### Benchmark results #####")
print(server.stdout.read().decode().strip())
print(client.stdout.read().decode().strip())
print("#############################")
def run(run_benchmark = False):
......
......@@ -17,7 +17,7 @@ client: client.c include/utils.h lib/list.o
.PHONY: clean run_client run_server random_file
# Construieste un fisier de 1MB (1024B*10^4)==1MB
# Construieste un fisier de 100KB (1024B*10^2)==1KB
random_file:
dd if=/dev/urandom of=file.bin bs=1024 count=100
......
......@@ -14,8 +14,8 @@ Topology:
L1 L2
client <--> router <--> server
Link 1 - 10 Mbps, 5ms delay, 20% packet loss (parameters set at topo.py:57)
Link 2 - 10 Mbps, 5ms delay, 20% packet loss (parameters set at topo.py:60)
Link 1 - 10 Mbps, 5ms delay, 10% packet loss (parameters set at topo.py:57)
Link 2 - 10 Mbps, 5ms delay, 10% packet loss (parameters set at topo.py:60)
client IP (h1) - 192.168.1.100
......@@ -46,7 +46,7 @@ typedef struct {
```C
list *window = create_list(2000);
list *window = create_list();
seq_udp p;
...
add_list_elem(list* window, &p, sizeof(struct seq_udp), p.seq);
......@@ -66,7 +66,7 @@ struct seq_udp {
To compile the code
```bash
make
# to create a random file of 1MB called file.bin
# to create a random file of 100KB called file.bin
make random_file
```
......@@ -74,8 +74,8 @@ This will create two binaries, to run them:
```bash
sudo python3 topo.py
```
It will open several terminals. We will run the client from `h1` and
the server from `h2`.
It will open several terminals. We will run the server from `h2` and
the client from `h1`.
## C++
Note, if you want to use C++, simply change the extension of `client.c` and
......
......@@ -7,16 +7,16 @@
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "common.h"
#include "utils.h"
#include "list.h"
#include "utils.h"
/* Max size of the datagrams that we will be sending */
// Max size of the datagrams that we will be sending
#define CHUNKSIZE MAX_SIZE;
#define SENT_FILENAME "file.bin"
#define SERVER_IP "172.16.0.100"
......@@ -51,33 +51,33 @@ void send_file_start_stop(int sockfd, struct sockaddr_in server_address,
d.seq = seq;
seq++;
/* TODO 1.2: Send the datagram. */
// TODO 1.1: Send the datagram.
// TODO 1.2: Wait for ACK before moving to the next datagram to send.
// If timeout or wrong seq number, resend the datagram.
/* TODO 1.3: Wait for ACK before moving to the next datagram to send. If timeout, resend the datagram. */
if (n == 0) // end of file
break;
}
}
void send_file_go_back_n(int sockfd, struct sockaddr_in server_address,
char *filename) {
char *filename) {
int fd = open(filename, O_RDONLY);
DIE(fd < 0, "open");
int rc;
/* TODO 2.1: Increase window size to a value that optimally uses the link */
// TODO 2.1: Increase window size to a value that optimally uses the link
int window_size = 5;
window->max_seq = 5;
int seq = 0;
// Read the entire file in chunks and add them into a list of seq_udp (window)
int seq = 1;
while (1) {
/* TODO: 1.1 Read all the data of the and add it as datagrams in
* datagram_queue */
/* Reads the content of a file */
struct seq_udp *d = malloc(sizeof(struct seq_udp));
DIE(d == NULL, "malloc");
int n = read(fd, d->payload, sizeof(d->payload));
DIE(n < 0, "read");
d->len = n;
......@@ -90,15 +90,14 @@ void send_file_go_back_n(int sockfd, struct sockaddr_in server_address,
break;
}
// TODO 2.2: Send window_size packets to the server to saturate the link
/* TODO 2.2: Send window_size packets to the server to saturate the link */
/* In a loop */
// In a loop, untill the list of packets is empty
/* TODO 2.2: On ACK remove from the list all the segments that have been ACKed
and send the next new segments added to the window */
// TODO 2.2: On ACK remove from the list all the segments that have been ACKed
// and send the next new segments added to the window
/* TODO 2.3: On timeout on recv resend all the segments from the window*/
// TODO 2.3: On timeout on recv resend all the segments from the window
}
void send_a_message(int sockfd, struct sockaddr_in server_address) {
......@@ -106,45 +105,43 @@ void send_a_message(int sockfd, struct sockaddr_in server_address) {
strcpy(d.payload, "Hello world!");
d.len = strlen("Hello world!");
/* Send a UDP datagram. Sendto is implemented in the kernel (network stack of
* it), it basically creates a UDP datagram, sets the payload to the data we
* specified in the buffer, and the completes the IP header and UDP header
* using the sever_address info.*/
// Send a UDP datagram. Sendto is implemented in the kernel (network stack of
// it), it basically creates a UDP datagram, sets the payload to the data we
// specified in the buffer, and the completes the IP header and UDP header
// using the sever_address info.
int rc = sendto(sockfd, &d, sizeof(struct seq_udp), 0,
(struct sockaddr *)&server_address, sizeof(server_address));
DIE(rc < 0, "send");
/* Receive the ACK. recvfrom is blocking with the current parameters */
// Receive the ACK. recvfrom is blocking with the current parameters
int ack;
rc = recvfrom(sockfd, &ack, sizeof(ack), 0, NULL, NULL);
}
int main(int argc, char *argv[]) {
int main(void) {
/* We use this structure to store the server info. IP address and Port.
* This will be written by the UDP implementation into the header */
// We use this structure to store the server info. IP address and Port.
// This will be written by the UDP implementation on recvfrom().
struct sockaddr_in servaddr;
int sockfd, rc;
// for benchmarking
TICK(TIME_A);
/* Our transmission window*/
// Our transmission window
window = create_list();
// Creating socket file descriptor. SOCK_DGRAM for UDP
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
DIE(sockfd < 0, "socket");
/* Set the timeout on the socket */
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
rc = setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
sizeof timeout);
// Set the timeout on the socket
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 250000; // 250ms
rc = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
DIE(rc < 0, "setsockopt");
// Fill the information that will be put into the IP and UDP header to
......@@ -154,16 +151,19 @@ int main(int argc, char *argv[]) {
servaddr.sin_port = htons(PORT);
inet_aton(SERVER_IP, &servaddr.sin_addr);
/* TODO: Read the demo function.
Implement and test (one at a time) each of the proposed versions for sending a
file. */
// TODO: Read the demo function.
// Implement and test (one at a time) each of the proposed versions for sending a
// file.
send_a_message(sockfd, servaddr);
// send_file_start_stop(sockfd, servaddr, SENT_FILENAME);
// send_file_window(sockfd, servaddr, SENT_FILENAME);
// send_file_go_back_n(sockfd, servaddr, SENT_FILENAME);
close(sockfd);
/* Print the runtime of the program */
free(window);
// Print the runtime of the program
TOCK(TIME_A);
return 0;
......
......@@ -3,7 +3,7 @@
#include <stdint.h>
#define MAXSIZE 128
#define MAXSIZE 1024
#define PORT 8313
struct seq_udp {
......
#ifndef _LIST_H_
#define _LIST_H_
/* List entry */
struct cel{
void* info;
// List entry
struct cel {
void *info;
int info_len;
int seq;
char type;
struct cel* next;
struct cel *next;
};
typedef struct cel list_entry;
/* Window as a list */
// Window as a list
typedef struct {
int size;
int max_seq;
list_entry* head;
}list;
list_entry *head;
} list;
/* Creates a list */
list* create_list();
/* Adds a segment to the window */
void add_list_elem(list* window, void* segment, int segment_size, int seq);
#endif /* _LIST_H_ */
// Creates a list
list *create_list();
// Adds a segment to the window
void add_list_elem(list *window, void *segment, int segment_size, int seq);
#endif // _LIST_H_
......@@ -2,60 +2,60 @@
#include <stdlib.h>
#include <string.h>
list* create_list() {
list* l = (list *)calloc(1, sizeof(list));
l->size = 0;
return l;
list *create_list() {
list *l = (list *)calloc(1, sizeof(list));
l->size = 0;
return l;
}
/* append order by seq */
void add_list_elem(list* list, void* info, int info_len, int seq) {
/* first check for duplicates seq */
list_entry* l_check = list->head;
while(l_check != NULL) {
if(l_check->seq == seq)
return;
l_check = l_check->next;
}
/* create list entry and set seq and type */
list_entry* l = (list_entry *)calloc(1, sizeof(list_entry));
l->seq = seq;
/* buffer info */
if(info_len > 0) {
l->info = calloc(info_len, sizeof(char));
memcpy(l->info, info, info_len);
l->info_len = info_len;
} else{
l->info = NULL;
}
/* first elem */
if(list->head == NULL) {
list->head = l;
} else {
list_entry* _l = list->head;
/* first elem */
if(_l->seq > seq) {
l->next = _l;
list->head = l;
list->size++;
return;
}
/* find elem place */
while(_l->next && _l->next->seq < seq) {
_l = _l->next;
}
l->next =_l->next;
_l->next = l;
}
list->size++;
// append order by seq
void add_list_elem(list *list, void *info, int info_len, int seq) {
/* first check for duplicates seq */
list_entry *l_check = list->head;
while (l_check != NULL) {
if (l_check->seq == seq)
return;
l_check = l_check->next;
}
// create list entry and set seq and type
list_entry *l = (list_entry *)calloc(1, sizeof(list_entry));
l->seq = seq;
// buffer info
if (info_len > 0) {
l->info = calloc(info_len, sizeof(char));
memcpy(l->info, info, info_len);
l->info_len = info_len;
} else {
l->info = NULL;
}
// first elem
if (list->head == NULL) {
list->head = l;
} else {
list_entry *_l = list->head;
// first elem
if (_l->seq > seq) {
l->next = _l;
list->head = l;
list->size++;
return;
}
// find elem place
while (_l->next && _l->next->seq < seq) {
_l = _l->next;
}
l->next = _l->next;
_l->next = l;
}
list->size++;
}
......@@ -21,23 +21,18 @@ int recv_seq_udp(int sockfd, struct seq_udp *seq_packet, int expected_seq) {
struct sockaddr_in client_addr;
socklen_t clen = sizeof(client_addr);
/* Receive a segment with seq_number seq_packet->seq */
// Receive a segment with seq_number seq_packet->seq
int rc = recvfrom(sockfd, seq_packet, sizeof(struct seq_udp), 0,
(struct sockaddr *)&client_addr, &clen);
/* TODO: Check if the sequence number is the expected one. if yes,
increase the expected sequence number after sending the ACK
return the number of bytes read.
// TODO: Check if the sequence number is the expected one.
/* TODO: If segment is not with the expected number, send ACK
with expected seqence number and return -1 */
// TODO: If we got the expected packet (by seq) send ACK for the seq.packet
// and return the number of bytes read.
// We will increase expected_seq in the calling function (recv_a_file(...))
int ack = 0;
// TODO: Sending ACK with expected sequence number */
rc = sendto(sockfd, &ack, sizeof(ack), 0, (struct sockaddr *)&client_addr,
clen);
DIE(rc < 0, "send");
// TODO: If segment is not with the expected number, send ACK
// for the last well received packet (expected_seq - 1) and return -1
}
void recv_a_file(int sockfd, char *filename) {
......@@ -48,19 +43,19 @@ void recv_a_file(int sockfd, char *filename) {
int rc;
while (1) {
/* Receive a chunk */
// Receive a chunk
rc = recv_seq_udp(sockfd, &p, expected_seq);
/* TODO: If rc == -1 => we didn't receive the expected segment. We continue */
// TODO: If rc == -1 => we didn't receive the expected segment. We continue (retry to receive the same chunk).
/* TODO: If rc >=0 => we receive the expected segment. We increase expected_seq */
// TODO: If rc >=0 => we receive the expected segment. We increase expected_seq
/* An empty payload means the file ended.
Break if file ended */
// An empty payload means the file ended.
if (p.len == 0)
// Break if file ended
break;
/* Write the chunk to the file */
// Write the chunk to the file
write(fd, p.payload, p.len);
}
......@@ -68,15 +63,15 @@ void recv_a_file(int sockfd, char *filename) {
}
void recv_a_message(int sockfd) {
/* Receive a datagram and send an ACK */
/* The info of the who sent the datagram (PORT and IP) */
// Receive a datagram and send an ACK
// The info of the who sent the datagram (PORT and IP)
struct sockaddr_in client_addr;
struct seq_udp p;
socklen_t clen = sizeof(client_addr);
int rc = recvfrom(sockfd, &p, sizeof(struct seq_udp), 0,
(struct sockaddr *)&client_addr, &clen);
/* We know it's a string so we print it*/
// We know it's a string so we print it
printf("[Server] Received: %s\n", p.payload);
int ack = 0;
......@@ -86,7 +81,7 @@ void recv_a_message(int sockfd) {
DIE(rc < 0, "send");
}
int main(int argc, char *argv[]) {
int main(void) {
int sockfd;
struct sockaddr_in servaddr;
......@@ -96,7 +91,7 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE);
}
/* Make ports reusable, in case we run this really fast two times in a row */
// Make ports reusable, in case we run this really fast two times in a row
int enable = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
perror("setsockopt(SO_REUSEADDR) failed");
......@@ -105,7 +100,7 @@ int main(int argc, char *argv[]) {
// datagrams have to be sent to our process.
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET; // IPv4
/* 0.0.0.0, basically match any IP */
// 0.0.0.0, basically match any IP
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
......
......@@ -53,12 +53,12 @@ class NetworkTopo( Topo ):
h2 = self.addHost( 'h2', ip='172.16.0.100/12',
defaultRoute='via 172.16.0.1' )
# 10 Mbps, 5ms delay, 10% packet loss
self.addLink( h1, router, intfName1='r0-eth1', bw=10, delay='5ms', loss=10,
# 10 Mbps, 10ms delay, 10% packet loss
self.addLink( h1, router, intfName1='r0-eth1', bw=10, delay='10ms', loss=10,
params1={ 'ip' : '192.168.1.1/24' }) # for clarity
# 10 Mbps, 5ms delay, 10% packet loss
self.addLink( h2, router, intfName2='r0-eth2', bw=10, delay='5ms', loss=10,
# 10 Mbps, 10ms delay, 10% packet loss
self.addLink( h2, router, intfName2='r0-eth2', bw=10, delay='10ms', loss=10,
params2={ 'ip' : '172.16.0.1/12' } )
class NetworkManager(object):
......
client
server
......@@ -9,7 +9,7 @@ CFLAGS = -Wall -g -Werror -Wno-error=unused-variable
PORT = 12345
# Adresa IP a serverului
IP_SERVER = 127.0.0.1
IP_SERVER = 192.168.0.2
all: server client
......
We write the implementation of a simple chat server.
`common.c` - implementations for sending and receiving a `struct chat_packet`
`server.c` - server code
`client.c` - client code
We use the following API today:
```c
// Create an endpoint for communication (usually on the network): the socket is
// modelled as a file descriptor.
int socket (int domain, int type, int protocol);
// Assign the address specified by addr to the socket referred to by sockfd.
// Other parties will be able to connect to this socket on the specified address.
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
// Connect the socket referred to by the file descriptor sockfd to the address
// specified by addr.
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
// Marks the socket referred to by sockfd as a passive socket (a socket that will
// be used to accept incoming connection requests using accept).
int listen(int sockfd, int backlog);
// When a connection request comes in on the listening socket referred to by
// sockfd, creates a new connected socket, and return a new file descriptor
// referring to that socket. The newly created socket can be used to communicate
// with the party which made the connection request.
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// Send at most len bytes of buf to socket sockfd. Returns the number sent or
// -1. For TCP sockets, this function returns when len bytes of buf have been
// accepted by the TCP/IP stack, and the stack guarantees they will be sent.
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
// Receive at most len bytes from sockfd into buf. This function blocks (if
// socket is not nonblocking) until some data is available on sockfd, and may
// return less bytes than len. The function returns how many bytes it wrote into
// buf.
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
```
We use the following structure for the messages exchanged by the server and the
clients:
```c
#define MSG_MAXSIZE 1024
struct chat_packet {
uint16_t len;
char message[MSG_MAXSIZE + 1];
};
```
## Topology
```
|‾‾‾‾‾‾‾‾|
client1 -- (r-eth1) | Router | (r-eth2) -- client2
|________|
(r-eth0)
¦
server
Interfaces
r-eth0: 192.168.0.1/24
r-eth1: 192.168.1.1/24
r-eth2: 192.168.2.1/24
```
## Usage
To compile the code
```
make
```
To start the topology (terminals for each device will be started as well):
```bash
sudo pkill ovs-test
sudo python3 topo.py
```
To start the `server`, in the `server` device, simply run `./server 192.168.0.2 [PORT]`.
To start a client, in a `client#` device, simply run `./client 192.168.0.2 [PORT]`.