Skip to content

Instantly share code, notes, and snippets.

@storbukas
Last active February 11, 2018 22:06
Show Gist options
  • Save storbukas/ec1e7ca97c9c1942c52e20143c9ebec0 to your computer and use it in GitHub Desktop.
Save storbukas/ec1e7ca97c9c1942c52e20143c9ebec0 to your computer and use it in GitHub Desktop.
DA-LBE socket option example
/*
* Author: Lars Erik Storbukås <larserik@storbukas.no>
* http://larserik.storbukas.no
* Date: 11/02-2018
*
* Description:
*
* Simple TCP client transferring a file to a destination with
* DA-LBE mechanisms enabled. This transfer has configured a
* probability of 5% of Phantom ECN signals (which reduce the
* transmission rate without dropping packets).
*
* Setup:
*
* This scripts sends a file located in the same directory as
* this script, called 'foobar.data' which is a file populated
* with random data. A file of 100 megabyte can be produced by
* issuing the following command:
*
* $ head -c 100MB < /dev/urandom > foobar.data
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <signal.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <linux/tcp.h> // for DA-LBE socket options
#include <limits.h> // for UINT_MAX
#define PORT 12345
#define LENGTH 1448
#define DESTINATION_IP "192.168.1.100"
#define INPUT_FILE "foobar.data"
void error(const char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char *argv[]) {
/* Variable Definition */
int sockfd;
int nsockfd;
char revbuf[LENGTH];
struct sockaddr_in remote_addr;
/* Get the Socket file descriptor */
if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1) {
error("ERROR: Failed to obtain Socket Descriptor!\n");
}
/* Fill the socket address struct */
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(PORT);
inet_pton(AF_INET, DESTINATION_IP, &remote_addr.sin_addr);
bzero(&(remote_addr.sin_zero), 8 );
/* Try to connect the remote */
if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1) {
error("ERROR: Failed to connect to the host!\n");
}
else {
printf("Connected to the host at port %d\n", PORT);
}
/* Send File to recipient */
char* fs_name = INPUT_FILE;
char sdbuf[LENGTH];
printf("Sending %s to %s\n", fs_name, DESTINATION_IP);
FILE *fs = fopen(fs_name, "r");
if(fs == NULL) {
printf("ERROR: File %s not found.\n", fs_name);
exit(1);
}
/* DA-LBE setsockopt */
int opt_da_lbe_mode = TCP_DA_LBE_ENABLED;
if (setsockopt(sockfd, IPPROTO_TCP, DA_LBE_MODE,
(char *)&opt_da_lbe_mode,
sizeof(opt_da_lbe_mode)) != 0) {
printf("Can't set data with setsockopt: DA_LBE_MODE\n");
exit(1);
}
unsigned int opt_ecn_probability = 0.05 * UINT_MAX; // 5% Phantom ECN probability
if (setsockopt(sockfd, IPPROTO_TCP, DA_LBE_INFO_ECN,
(char *)&opt_ecn_probability,
sizeof(opt_ecn_probability)) != 0) {
printf("Can't set data with setsockopt: DA_LBE_INFO_ECN\n");
exit(1);
}
bzero(sdbuf, LENGTH);
int fs_block_sz;
while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs)) > 0) {
if(send(sockfd, sdbuf, fs_block_sz, 0) < 0) {
printf("ERROR: Failed to send file %s.\n", fs_name);
break;
}
bzero(sdbuf, LENGTH);
}
printf("Transfer of %s done!\n", fs_name);
/* DA-LBE setsockopt */
struct da_lbe_info da_lbe_info;
unsigned short da_lbe_info_length = sizeof(da_lbe_info);
if (getsockopt(sockfd, IPPROTO_TCP, DA_LBE_INFO,
(void *)&da_lbe_info,
(socklen_t *)&da_lbe_info_length) != 0) {
printf("ERROR: Failed to fetch DA_LBE_INFO\n");
} else {
printf("Number of phantom ECNs generated: %u\n", da_lbe_info.dalbe_phantom_ecn_count);
}
close(fs);
close (sockfd);
printf("Connection closed.\n");
return (0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment