summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c287
1 files changed, 101 insertions, 186 deletions
diff --git a/src/main.c b/src/main.c
index 3fb9a4a..2e0f391 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,162 +16,119 @@
//
#include <stdlib.h>
#include <stdio.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <strings.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <wait.h>
+#include <string.h>
+
+#include "common.h"
+#include "test.h"
+
+
+void get_help() {
+ printf(
+ "\n"
+ "Cnetbench is a simple protocol-agnostic network benchmarking program.\n"
+ "Simply put, it is a fire-hydrant of data and sends as much data as is\n"
+ "allowed, and reports what those numbers are. This can be single stream\n"
+ "or multiple concurrent data streams.\n"
+ "\n"
+ "Usage:\n\n"
+ " cnetbench -d <destination> -p <port> [-m <megabytes>] [-c <stream_count>]"
+ "\n\n");
+}
//
-// Watches an array of pids for their exit, and updates the output array
-// exit_times with each pid's exit timeval struct timestamp (epoch with
-// microseconds).
-//
-// Note that this function does not start the pids, but only watches them. To
-// calculate runtime, external code needs to track when the pids were created.
-//
-// @param pids Array of pid_t pids to be watched
-// @param count Number of pids in the pids array
-// @param exit_times Array of timeval structs that will contain exit times for
-// all of the pids in the array. Must be at least the size of
-// the pids array or unpredictable behavior may result.
+// Prints test results in a friendly, human-readable format.
//
-// @return int Overall status of all exited pids (if any fail exit, returns 1)
+// @param t_test* Test type containing test parameters
+// @param start_times Array of child start times, ordered by child process index
+// @param exit_times Array of child exit times, ordered by child process index
//
-int time_pids(pid_t* pids, int count, struct timeval *exit_times) {
- int i;
- int waiting = 1;
-
- while(waiting != 0) {
- waiting = 0;
- for(i = 0; i < count; i++) {
- // Pid with this index has exited, skip it.
- if(pids[i] == 0)
- continue;
-
- // 0 = state change (exit)
- if(waitpid(pids[i], NULL, WNOHANG) != 0) {
- // Child has exited
- pids[i] = 0;
- // Write the exit time
- gettimeofday(&exit_times[i], NULL);
- } else {
- waiting = 1;
- }
- }
- sleep(1);
- }
- return 0;
-}
+void print_results(t_test *t,
+ struct timeval *start_times,
+ struct timeval *exit_times) {
+ // Clear a little space
+ printf("\n\n");
+ long total_amount = t->amount * t->streams;
+ double total_time = 0;
-//
-// Performs a benchmark test on the specified destination/port, sending the
-// specified amount of data.
-//
-// @param amount Megabytes to send
-// @param dest Destination host to send data to
-// @param port Destination port to send the data on
-//
-// @return int Succcess (0) or failure (1) of data send
-//
-int test(int amount, char *dest, int port) {
- int socket_desc;
- // This is 1 megabyte
- long size = 1048576;
- char *message = calloc(size, 1);
-
- // AF_INET: ipv4 (AF_INET6 would be ipv6)
- // SOCK_STREAM: TCP
- // 0: Protocol 0 (IP)
- socket_desc = socket(AF_INET, SOCK_STREAM, 0);
-
- if(socket_desc == -1) {
- printf("Error creating socket\n");
- return 1;
- }
+ for(int i = 0; i < t->streams; i++) {
+ // calculate average transfer rate for this thread
- // Set socket values
- struct sockaddr_in server;
- server.sin_addr.s_addr = inet_addr(dest);
- server.sin_family = AF_INET;
- server.sin_port = htons(port);
+ // Second difference, multiplied by 1000 to make room for microseconds
+ double time_s = 1000 * (exit_times[i].tv_sec - start_times[i].tv_sec);
+ // Microsecond difference
+ double time_ms = exit_times[i].tv_usec - start_times[i].tv_usec;
+ // Sum of microsecond and second differences
+ double time = (time_s + time_ms) / 1000;
- if(connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0) {
- printf("Connection error\n");
- return -1;
- }
- printf("Connected\n");
+ // Append duration to the total duration of transfers.
+ total_time += time;
- // Send some data
- long i = 0;
- while(i < amount) {
- if(send(socket_desc, message, size, 0) < 0) {
- return -1;
- }
- i++;
+ double avg = t->amount / time;
+
+ printf("Fork %d/%d transferred %d MB in %.4f seconds, averaging %.2f MB/s\n",
+ i + 1,
+ t->streams,
+ t->amount,
+ time,
+ avg
+ );
}
- free(message);
- return 0;
+ printf("\n%d forks transferred a total of %ld MBs in %.2f parallel seconds\n",
+ t->streams,
+ total_amount,
+ total_time
+ );
}
//
-// Forks sub-processes off stream_count times, to test bandwidth to the
-// specified destination host/port, sending the specified amount of data.
-//
-// Note that start_times and exit_times are two arrays that will receive start
-// and exit timestamps for each pid for timing purposes.
-//
-// @param amount Amount of data in megabytes to send
-// @param stream_count Number of data streams to test concurrently
-// @param dest Destination host to send data to
-// @param port Destination port to send data over
-// @param start_times Output array of timeval start time timestamps
-// @param exit_times Output array of timeval exit time timestamps
-//
-// @return int Success (0) or failure(1)
-//
-int spawn_tests(int amount,
- int stream_count,
- char* dest,
- int port,
- struct timeval *start_times,
- struct timeval *exit_times) {
- pid_t pids[stream_count];
-
- pid_t pid;
- int i = 0;
- while(i < stream_count) {
- // Fork
- pid = fork();
-
- if(pid == 0) {
- // Execute the test
- printf("Fork %d starting\n", i);
- test(amount, dest, port);
- exit(0);
- } else if(pid > 0) {
- // parent
- pids[i] = pid;
- // Set start time
- gettimeofday(&start_times[i], NULL);
- i++;
+// Parses the program arguments and populates a t_test type with the values
+// specified by the user.
+//
+// @param argc Number of arguments passed to the program (the main argc)
+// @param argv Arguments passed to the program (the main argv)
+// @param test T_test object to be populated
+//
+int parse_args(int argc, char *argv[], t_test *test) {
+ int i = 1;
+
+ char server = 0;
+ char port = 0;
+
+ while(i < argc) {
+ if(strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--megabytes") == 0) {
+ ++i;
+ test->amount = atoi(argv[i]);
+ } else if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--count") == 0) {
+ ++i;
+ test->streams = atoi(argv[i]);
+ } else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--dest") == 0) {
+ ++i;
+ strcpy(test->server, argv[i]);
+ server = 1;
+ } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--port") == 0) {
+ ++i;
+ test->port = atoi(argv[i]);
+ port = 1;
} else {
- // failure
- printf("%d: Failure\n", i);
+ get_help();
return 1;
}
+ ++i;
}
- // Wait for all children to exit, and clock their exit time
- time_pids(pids, stream_count, exit_times);
+ if(server == 0) {
+ printf("Please specify a destination server (-d,--dest) to test with.\n");
+ return 1;
+ }
+ if(port == 0) {
+ printf("Please specify a port (-p,--port) to run tests over.\n");
+ return 1;
+ }
- printf("Fin!\n");
return 0;
}
@@ -180,63 +137,21 @@ int spawn_tests(int amount,
// Ye olde main
//
int main(int argc, char *argv[]) {
- int amount;
- int stream_count;
- char *server;
- int port;
-
- if(argc != 5) {
- printf("\nUsage:\n");
- printf(" %s <megabytes> <stream_count> <server-ip> <port>\n\n", argv[0]);
- return 1;
- }
+ t_test test;
+ // Initialize the test object with defaults
+ new_test(&test);
// Parse program arguments
- amount = atoi(argv[1]);
- stream_count = atoi(argv[2]);
- server = argv[3];
- port = atoi(argv[4]);
+ int arg_status = parse_args(argc, argv, &test);
- struct timeval start_times[stream_count];
- struct timeval exit_times[stream_count];
-
- spawn_tests(amount, stream_count, server, port, start_times, exit_times);
-
- // Clear a little space
- printf("\n\n");
-
- long total_amount = amount * stream_count;
- double total_time = 0;
-
- for(int i = 0; i < stream_count; i++) {
- // calculate average transfer rate for this thread
-
- // Second difference, multiplied by 1000 to make room for microseconds
- double time_s = 1000 * (exit_times[i].tv_sec - start_times[i].tv_sec);
- // Microsecond difference
- double time_ms = exit_times[i].tv_usec - start_times[i].tv_usec;
- // Sum of microsecond and second differences
- double time = (time_s + time_ms) / 1000;
+ if(arg_status > 0)
+ return 1;
- // Append duration to the total duration of transfers.
- total_time += time;
+ struct timeval start_times[test.streams];
+ struct timeval exit_times[test.streams];
- double avg = amount / time;
+ test_start_all(&test, start_times, exit_times);
+ print_results(&test, start_times, exit_times);
- printf("Fork %d/%d transferred %d MB in %.4f seconds, averaging %.2f MB/s\n",
- i + 1,
- stream_count,
- amount,
- time,
- avg
- );
- }
-
- printf("\n%d forks transferred a total of %ld MBs in %.2f parallel seconds\n",
- stream_count,
- total_amount,
- total_time
- );
-
return 0;
}

Generated by cgit