summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgnn <gnn@FreeBSD.org>2008-04-24 06:56:45 +0000
committergnn <gnn@FreeBSD.org>2008-04-24 06:56:45 +0000
commit0248cb5a7774eff1141218463b802240ee14f5b4 (patch)
treed9a0f9f77b28bd3a9b6d8c49c0553d4cb2231fc5
parent53e28a2a3ad9d4b91d7ee258cbd6668dd7a412e5 (diff)
downloadFreeBSD-src-0248cb5a7774eff1141218463b802240ee14f5b4.zip
FreeBSD-src-0248cb5a7774eff1141218463b802240ee14f5b4.tar.gz
Updated the test to handle multiple sinks. The sinks cut their
transmissions by the number of them running so that they do not overwhelm the source. Added a simple shell script to kick off sinks on multiple hosts as well as a source on the host where the shell script is run. The script also collects the output of all the sinks and the source into files named for the host on which the tests are run. A date is appended to each output file to make it unique per run.
-rw-r--r--tools/tools/mctest/mctest.115
-rw-r--r--tools/tools/mctest/mctest.cc106
-rw-r--r--tools/tools/mctest/mctest_run.sh67
3 files changed, 148 insertions, 40 deletions
diff --git a/tools/tools/mctest/mctest.1 b/tools/tools/mctest/mctest.1
index c840810..17729f2 100644
--- a/tools/tools/mctest/mctest.1
+++ b/tools/tools/mctest/mctest.1
@@ -36,7 +36,9 @@
.Op Fl n Ar number
.Op Fl s Ar size
.Op Fl t Ar inter-packet gap
-.Op Fl r
+.Op Fl M Ar number of clients (source only)
+.Op Fl m Ar my client number (sink only)
+.Op Fl r
.Sh DESCRIPTION
The
.Nm
@@ -48,7 +50,8 @@ the time at which they're received and then reflects them back
over unicast to the source. When the source has captured all
the reflected packets it prints out the round trip time of each.
.Pp
-The sink prints out the time between the packets received.
+The source prints out the round trip time of packets sent to the
+sinks. The sink prints out the time between the packets received.
.Pp
The options are as follows:
.Bl -tag -width ".Fl d Ar argument"
@@ -60,6 +63,10 @@ Packet size in bytes.
Number of packets.
.It Fl t Ar gap
Inter-packet gap in nanoseconds.
+.It Fl M Ar clients
+The number of clients that are listening
+.It Fl m Ar my number
+The client's number 0, 1, etc.
.It Fl r
This version of
.Nm
@@ -73,9 +80,9 @@ of the
command:
.Pp
Source
-.Dl "mctest -i em0 -s 1024 -n 100 -t 1"
+.Dl "mctest -i em0 -M 1 -s 1024 -n 100 -t 1"
Sink
-.Dl "mctest -i em0 -s 1024 -n 100 -r"
+.Dl "mctest -i em0 -m 0 -s 1024 -n 100 -r"
.Pp
Send 100 packets of 1024 bytes, with an inter-packet gap of 1 nanosecond.
.Pp
diff --git a/tools/tools/mctest/mctest.cc b/tools/tools/mctest/mctest.cc
index d59ddff..436efce 100644
--- a/tools/tools/mctest/mctest.cc
+++ b/tools/tools/mctest/mctest.cc
@@ -61,7 +61,7 @@ using namespace std;
//
void usage()
{
- cout << "mctest -i interface -g multicast group -s packet size -n number -t inter-packet gap\n";
+ cout << "mctest [-r] -M clients -m client number -i interface -g multicast group -s packet size -n number -t inter-packet gap\n";
exit(-1);
}
@@ -86,10 +86,13 @@ void usage(string message)
// @param group ///< multicast group
// @param pkt_size ///< packet Size
// @param number ///< number of packets we're expecting
+// @param clients ///< total number of clients (N)
+// @param client ///< our client number (0..N)
//
// @return 0 for 0K, -1 for error, sets errno
//
-int sink(char *interface, struct in_addr *group, int pkt_size, int number) {
+int sink(char *interface, struct in_addr *group, int pkt_size, int number,
+ int clients, int client) {
int sock, backchan;
@@ -172,11 +175,18 @@ int sink(char *interface, struct in_addr *group, int pkt_size, int number) {
perror("recvfrom failed");
return -1;
}
- recvd.sin_port = htons(SERVER_PORT);
- if (sendto(backchan, packet, pkt_size, 0,
- (struct sockaddr *)&recvd, sizeof(recvd)) < 0) {
- perror("sendto failed");
- return -1;
+ /*
+ * Bandwidth limiting. If there are N clients then we want
+ * 1/N packets from each, otherwise the clients will overwhelm
+ * the sender.
+ */
+ if (n % clients == client) {
+ recvd.sin_port = htons(SERVER_PORT + client);
+ if (sendto(backchan, packet, pkt_size, 0,
+ (struct sockaddr *)&recvd, sizeof(recvd)) < 0) {
+ perror("sendto failed");
+ return -1;
+ }
}
gettimeofday(&packets[ntohl(*(int *)packet)], 0);
n++;
@@ -208,10 +218,11 @@ int sink(char *interface, struct in_addr *group, int pkt_size, int number) {
//
// Structure to hold thread arguments
//
-typedef struct server_args {
+struct server_args {
struct timeval *packets; ///< The timestamps of returning packets
int number; ///< Number of packets to expect.
int pkt_size; ///< Size of the packets
+ int client; ///< Which client we listen for
};
//
@@ -238,7 +249,7 @@ void* server(void *passed) {
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = htons(SERVER_PORT);
+ addr.sin_port = htons(SERVER_PORT + args->client);
addr.sin_len = sizeof(addr);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
@@ -279,11 +290,12 @@ void* server(void *passed) {
// @param pkt_size ///< packet size
// @param number ///< number of packets
// @param gap ///< inter packet gap in nano-seconds
+// @param clients ///< number of clients we intend to run
//
// @return 0 for OK, -1 for error, sets errno
//
int source(char *interface, struct in_addr *group, int pkt_size,
- int number, int gap) {
+ int number, int gap, int clients) {
int sock;
struct sockaddr_in addr;
@@ -346,18 +358,21 @@ int source(char *interface, struct in_addr *group, int pkt_size,
*(int *)packets[i] = htonl(i);
}
- struct timeval received[number];
struct timeval sent[number];
- server_args args;
- pthread_t thread;
- args.packets = received;
- args.number = number;
- args.pkt_size = pkt_size;
-
- if (pthread_create(&thread, NULL, server, &args) < 0) {
- perror("failed to create server thread");
- return -1;
- }
+ struct timeval received[clients][number];
+ server_args args[clients];
+ pthread_t thread[clients];
+
+ for (int i = 0;i < clients; i++) {
+ args[i].pkt_size = pkt_size;
+ args[i].packets = received[i];
+ args[i].number = number / clients;
+ args[i].client = i;
+ if (pthread_create(&thread[i], NULL, server, &args[i]) < 0) {
+ perror("failed to create server thread");
+ return -1;
+ }
+ }
struct timespec sleeptime;
sleeptime.tv_sec = 0;
@@ -377,16 +392,23 @@ int source(char *interface, struct in_addr *group, int pkt_size,
}
}
- if (pthread_join(thread, NULL) < 0) {
- perror("failed to join thread");
- return -1;
- }
-
+ for (int i = 0; i < clients; i++) {
+ if (pthread_join(thread[i], NULL) < 0) {
+ perror("failed to join thread");
+ return -1;
+ }
+ }
+
timeval result;
- for (int i = 0; i < number; i++) {
- timersub(&args.packets[i], &sent[i], &result);
- cout << "sec: " << result.tv_sec;
- cout << " usecs: " << result.tv_usec << endl;
+ for (int client = 0;client < clients; client++) {
+ cout << "Results from client #" << client << endl;
+ for (int i = 0; i < number; i++) {
+ if (i % clients != client)
+ continue;
+ timersub(&args[client].packets[i], &sent[i], &result);
+ cout << "sec: " << result.tv_sec;
+ cout << " usecs: " << result.tv_usec << endl;
+ }
}
return 0;
@@ -415,12 +437,14 @@ int main(int argc, char**argv)
int pkt_size = 0; ///< packet size
int gap = 0; ///< inter packet gap (in nanoseconds)
int number = 0; ///< number of packets to transmit
- bool server = false;
+ bool server = false; ///< are we on he receiving end of multicast
+ int client = 0; ///< for receivers which client are we
+ int clients = 1; ///< for senders how many clients are there
- if (argc < 2 || argc > 11)
+ if (argc < 2 || argc > 14)
usage();
- while ((ch = getopt(argc, argv, "g:i:n:s:t:rh")) != -1) {
+ while ((ch = getopt(argc, argv, "M:m:g:i:n:s:t:rh")) != -1) {
switch (ch) {
case 'g':
group = new (struct in_addr );
@@ -433,7 +457,7 @@ int main(int argc, char**argv)
break;
case 'n':
number = atoi(optarg);
- if (number < 0 || number > 10000)
+ if (number < 0 || number > INT_MAX)
usage(argv[0] + string(" Error: ") + optarg +
string(" number of packets out of range"));
break;
@@ -452,6 +476,12 @@ int main(int argc, char**argv)
case 'r':
server = true;
break;
+ case 'm':
+ client = atoi(optarg);
+ break;
+ case 'M':
+ clients = atoi(optarg);
+ break;
case 'h':
usage(string("Help\n"));
break;
@@ -459,9 +489,13 @@ int main(int argc, char**argv)
}
if (server) {
- sink(interface, group, pkt_size, number);
+ if (clients <= 0 || client < 0)
+ usage("must specify client (-m) and number of clients (-M)");
+ sink(interface, group, pkt_size, number, clients, client);
} else {
- source(interface, group, pkt_size, number, gap);
+ if (clients <= 0)
+ usage("must specify number of clients (-M)");
+ source(interface, group, pkt_size, number, gap, clients);
}
}
diff --git a/tools/tools/mctest/mctest_run.sh b/tools/tools/mctest/mctest_run.sh
new file mode 100644
index 0000000..ec41d37
--- /dev/null
+++ b/tools/tools/mctest/mctest_run.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# A program to act as a test harness for the mctest program
+#
+# $FreeBSD$
+#
+# Defaults
+size=1024
+number=100
+group=""
+interface="cxgb0"
+remote="ssh"
+command="/sources/FreeBSD.CURRENT/src/tools/tools/mctest/mctest"
+gap=1000
+
+# Arguments are s (size), g (group), n (number), and c (command) followed
+# by a set of hostnames.
+args=`getopt s:g:n:c:i: $*`
+if [ $? != 0 ]
+then
+ echo 'Usage: mctest_run -s size -g group -n number -c remote command host1 host2 hostN'
+ exit 2
+fi
+set == $args
+count=0
+for i
+do
+ case "$i"
+ in
+ -s)
+ size=$3;
+ shift 2;;
+ -n)
+ number=$3;
+ shift 2;;
+ -g)
+ group=$3;
+ shift 2;;
+ -c)
+ command=$3;
+ shift 2;;
+ -i)
+ interface=$3;
+ shift 2;;
+ --)
+ shift; break;;
+ esac
+done
+
+#
+# Start our remote sink/reflectors
+#
+shift;
+current=0
+now=`date "+%Y%m%d%H%M"`
+for host in $*
+do
+ output=$host\_$interface\_$size\_$number\.$now
+ $remote $host $command -r -M $# -m $current -n $number -s $size -i $interface > $output &
+ sleep 1
+ current=`expr $current + 1 `;
+done
+
+#
+# Start the source/collector on this machine
+#
+$command -M $# -n $number -s $size -i le1 -t $gap > `uname -n`\_$size\_$number\.$now
OpenPOWER on IntegriCloud