diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2016-07-28 10:29:03 +0100 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2016-07-28 10:29:03 +0100 |
commit | 2539c359f67817984008a65cf613d32cd07c1120 (patch) | |
tree | 2f82b23610e1bf9d224f6121632ff7d8e2d3a026 | |
parent | 48a1c146116f7695a8cb7e19d2155cca87156490 (diff) |
initial client/server implementation
Allows to restrict latency/bandwidth between 2 machines.
This require to setup both machines pointing to each other.
Works but it's hard to change parameters.
To do that both end encapsulate packets in a UDP packet (the UDP data
it's just the packet received from tun interface). Quite easy but works.
Would be easier if server will be launched just with a port specification
while client with all parameters so to make easier to change.
-rw-r--r-- | latency.c | 4 | ||||
-rw-r--r-- | tun.c | 85 | ||||
-rw-r--r-- | tun.h | 1 |
3 files changed, 86 insertions, 4 deletions
@@ -55,7 +55,7 @@ unsigned rate_bytes; static void usage(void) { - fprintf(stderr, "syntax: latency <latency> <rate>\n"); + fprintf(stderr, "syntax: latency <latency> <rate> [<ip> <port>]\n"); exit(EXIT_FAILURE); } @@ -102,6 +102,8 @@ main(int argc, char **argv) latency_us = parse_value(argv[1], 0, 10000000, latency_units); rate_bytes = parse_value(argv[2], 1, INT_MAX, rate_units); + if (argc >= 5) + tun_set_ip_port(argv[3], atoi(argv[4])); setup_signals(); @@ -3,6 +3,9 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <poll.h> +#include <errno.h> +#include <stdbool.h> #include <sys/socket.h> #include <linux/if.h> #include <linux/if_tun.h> @@ -21,6 +24,7 @@ #include "utils.h" static int tun_fd = -1; +static int remote_sock = -1; /** * @param dev name of interface. MUST have enough @@ -84,6 +88,52 @@ tun_setup(void) tun_fd = fd; } +static void +create_remote_socket(void) +{ + remote_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (remote_sock < 0) { + perror("socket"); + exit(EXIT_FAILURE); + } +} + +void +tun_set_ip_port(const char *ip, int port) +{ + static in_addr_t redirect_ip; + + if (port < 1 || port > 65535) { + fprintf(stderr, "Wrong port value %d\n", port); + exit(EXIT_FAILURE); + } + + redirect_ip = inet_addr(ip); + if (redirect_ip == INADDR_NONE) { + fprintf(stderr, "Wrong ip format %s\n", ip); + exit(EXIT_FAILURE); + } + + create_remote_socket(); + + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons((short) port); + + sin.sin_addr.s_addr = INADDR_ANY; + if (bind(remote_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + perror("bind"); + exit(EXIT_FAILURE); + } + + sin.sin_addr.s_addr = redirect_ip; + if (connect(remote_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } +} + #define MIN_PKT_LEN 2000u #define PKT_BUF_LEN (1024u * 1024u * 32u) #define NUM_FLOWS 2 @@ -202,7 +252,10 @@ writer_proc(void *ptr) uint64_t curr_time = get_time_us(); if (pkt->time_to_send > curr_time) usleep(pkt->time_to_send - curr_time); - write(tun_fd, pkt->data, pkt->len); + if (remote_sock >= 0) + send(remote_sock, pkt->data, pkt->len, MSG_NOSIGNAL); + else + write(tun_fd, pkt->data, pkt->len); release_packet(pkt); } return NULL; @@ -235,8 +288,33 @@ handle_tun(void) uint64_t tot_bytes = 0; uint32_t num_packets = 0; - while (!term && (pkt = alloc_packet())) { - int len = read(tun_fd, pkt->data, MIN_PKT_LEN); + struct pollfd fds[2]; + fds[0].fd = tun_fd; + fds[0].events = POLLIN; + fds[1].fd = remote_sock; + fds[1].events = POLLIN; + fds[1].revents = 0; + + pkt = alloc_packet(); + while (!term) { + if (poll(fds, 2, -1) < 0) { + if (errno != EINTR) + break; + continue; + } + + int len; + if (fds[1].revents & POLLIN) { + len = recv(remote_sock, pkt->data, MIN_PKT_LEN, 0); + if (len <= 0) + break; + write(tun_fd, pkt->data, len); + continue; + } else if (fds[0].revents & POLLIN) { + len = read(tun_fd, pkt->data, MIN_PKT_LEN); + } else { + continue; + } if (len < 0) break; @@ -279,5 +357,6 @@ handle_tun(void) ip->daddr = addr; add_packet(flow, pkt); + pkt = alloc_packet(); } } @@ -1,3 +1,4 @@ void tun_setup(void); +void tun_set_ip_port(const char *ip, int port); void handle_tun(void); |