View | Details | Raw Unified | Return to bug 179085 | Differences between
and this patch

Collapse All | Expand All

(-)tools/tools/netrate/netblast/Makefile (+3 lines)
Lines 4-8 Link Here
4
4
5
PROG=	netblast
5
PROG=	netblast
6
NO_MAN=
6
NO_MAN=
7
LDFLAGS += -lpthread
8
9
WARNS?= 3
7
10
8
.include <bsd.prog.mk>
11
.include <bsd.prog.mk>
(-)tools/tools/netrate/netblast/netblast.c (-61 / +148 lines)
Lines 40-54 Link Here
40
#include <string.h>
40
#include <string.h>
41
#include <unistd.h>			/* close */
41
#include <unistd.h>			/* close */
42
42
43
#include <pthread.h>
44
#include <fcntl.h>
45
#include <time.h>   /* clock_getres() */
46
47
static int round_to(int n, int l)
48
{
49
    return ((n + l - 1)/l)*l;
50
}
51
43
static void
52
static void
44
usage(void)
53
usage(void)
45
{
54
{
46
55
47
	fprintf(stderr, "netblast [ip] [port] [payloadsize] [duration]\n");
56
	fprintf(stderr, "netblast [ip] [port] [payloadsize] [duration] [nthreads]\n");
48
	exit(-1);
57
	exit(-1);
49
}
58
}
50
59
51
static int	global_stop_flag;
60
static int	global_stop_flag=0;
52
61
53
static void
62
static void
54
signal_handler(int signum __unused)
63
signal_handler(int signum __unused)
Lines 57-104 Link Here
57
	global_stop_flag = 1;
66
	global_stop_flag = 1;
58
}
67
}
59
68
69
60
/*
70
/*
61
 * Loop that blasts packets: begin by recording time information, resetting
71
 * Each socket uses multiple threads so the generator is
62
 * stats.  Set the interval timer for when we want to wake up.  Then go.
72
 * more efficient. A collector thread runs the stats.
63
 * SIGALRM will set a flag indicating it's time to stop.  Note that there's
64
 * some overhead to the signal and timer setup, so the smaller the duration,
65
 * the higher the relative overhead.
66
 */
73
 */
67
static int
74
struct td_desc {
68
blast_loop(int s, long duration, u_char *packet, u_int packet_len)
75
	pthread_t td_id;
69
{
76
	uint64_t counter; /* tx counter */
70
	struct timespec starttime, tmptime;
77
	uint64_t send_errors; /* tx send errors */
71
	struct itimerval it;
78
	uint64_t send_calls;    /* tx send calls */
72
	u_int32_t counter;
79
	int s;
73
	int send_errors, send_calls;
80
	u_char *packet;
74
81
	u_int packet_len;
75
	if (signal(SIGALRM, signal_handler) == SIG_ERR) {
82
};
76
		perror("signal");
77
		return (-1);
78
	}
79
80
	if (clock_getres(CLOCK_REALTIME, &tmptime) == -1) {
81
		perror("clock_getres");
82
		return (-1);
83
	}
84
85
	if (clock_gettime(CLOCK_REALTIME, &starttime) == -1) {
86
		perror("clock_gettime");
87
		return (-1);
88
	}
89
90
	it.it_interval.tv_sec = 0;
91
	it.it_interval.tv_usec = 0;
92
	it.it_value.tv_sec = duration;
93
	it.it_value.tv_usec = 0;
94
83
95
	if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
84
static void *
96
		perror("setitimer");
85
blast(void *data)
97
		return (-1);
86
{
98
	}
87
    struct td_desc *t = data;
99
88
	t->counter=0;
100
	send_errors = send_calls = 0;
89
	t->send_errors=0;
101
	counter = 0;
90
	t->send_calls=0;
102
	while (global_stop_flag == 0) {
91
	while (global_stop_flag == 0) {
103
		/*
92
		/*
104
		 * We maintain and, if there's room, send a counter.  Note
93
		 * We maintain and, if there's room, send a counter.  Note
Lines 110-141 Link Here
110
		 * operation, causing the current sequence number also to be
99
		 * operation, causing the current sequence number also to be
111
		 * skipped.
100
		 * skipped.
112
		 */
101
		 */
113
		if (packet_len >= 4) {
102
		if (t->packet_len >= 4) {
114
			be32enc(packet, counter);
103
			be32enc(t->packet, t->counter);
115
			counter++;
104
			t->counter++;
116
		}
105
		}
117
		if (send(s, packet, packet_len, 0) < 0)
106
		if (send(t->s, t->packet, t->packet_len, 0) < 0)
118
			send_errors++;
107
			t->send_errors++;
119
		send_calls++;
108
		t->send_calls++;
120
	}
109
	}
110
    return NULL;
111
}
112
113
static struct td_desc **
114
make_threads(int s, u_char *packet, u_int packet_len, int nthreads)
115
{
116
    int i;
117
    int lb = round_to(nthreads * sizeof (struct td_desc *), 64);
118
    int td_len = round_to(sizeof(struct td_desc), 64); // cache align
119
    char *m = calloc(1, lb + td_len * nthreads);
120
    struct td_desc **tp;
121
122
    /* pointers plus the structs */
123
    if (m == NULL) {
124
        perror("no room for pointers!");
125
        exit(1);
126
    }
127
    tp = (struct td_desc **)m;
128
    m += lb;    /* skip the pointers */
129
    for (i = 0; i < nthreads; i++, m += td_len) {
130
        tp[i] = (struct td_desc *)m;
131
        tp[i]->s = s;
132
        tp[i]->packet = packet;
133
        tp[i]->packet_len = packet_len;
134
        if (pthread_create(&tp[i]->td_id, NULL, blast, tp[i])) {
135
            perror("unable to create thread");
136
            exit(1);
137
        }
138
    }
139
    return tp;
140
}
121
141
142
143
static void
144
main_thread(struct td_desc **tp, long duration, struct timespec starttime, struct timespec tmptime, long payloadsize, int family, int nthreads)
145
{
146
	uint64_t send_errors=0, send_calls=0;
147
	int i;
122
	if (clock_gettime(CLOCK_REALTIME, &tmptime) == -1) {
148
	if (clock_gettime(CLOCK_REALTIME, &tmptime) == -1) {
123
		perror("clock_gettime");
149
		perror("clock_gettime");
124
		return (-1);
125
	}
150
	}
126
151
152
	for (i = 0; i < nthreads; i++) {
153
		/* Wait for thread end */
154
		pthread_join( tp[i]->td_id, NULL);
155
		send_calls+=tp[i]->send_calls;
156
		send_errors+=tp[i]->send_errors;
157
    }
158
127
	printf("\n");
159
	printf("\n");
128
	printf("start:             %zd.%09lu\n", starttime.tv_sec,
160
	printf("start:                      %zd.%09lu\n", starttime.tv_sec,
129
	    starttime.tv_nsec);
161
	    starttime.tv_nsec);
130
	printf("finish:            %zd.%09lu\n", tmptime.tv_sec,
162
	printf("finish:                     %zd.%09lu\n", tmptime.tv_sec,
131
	    tmptime.tv_nsec);
163
	    tmptime.tv_nsec);
132
	printf("send calls:        %d\n", send_calls);
164
	printf("send calls:                 %lu\n", send_calls);
133
	printf("send errors:       %d\n", send_errors);
165
	printf("send errors:                %lu\n", send_errors);
134
	printf("approx send rate:  %ld\n", (send_calls - send_errors) /
166
	printf("send success:               %lu\n", send_calls - send_errors);
167
	printf("approx send rate:           %lu\n", (send_calls - send_errors) /
135
	    duration);
168
	    duration);
136
	printf("approx error rate: %d\n", (send_errors / send_calls));
169
	printf("approx error rate:          %lu\n", (send_errors / send_calls));
137
170
	printf("approx Ethernet throughput: ");
138
	return (0);
171
	if (family == AF_INET)
172
		printf("%ld Mib/s\n", ((send_calls - send_errors) / duration ) *
173
		(payloadsize + 8 + 20 + 14 ) * 8 / 1000 / 1000);                                                                   
174
	else if (family == AF_INET6)
175
		printf("%ld Mib/s\n", ((send_calls - send_errors) / duration ) *
176
		(payloadsize + 8 + 40 + 14 ) * 8 / 1000 / 1000);
177
	else printf("CAN 'T DETERMINE family type %i\n",family);
178
	printf("approx payload throughput:  %ld Mib/s\n", ((send_calls - send_errors) / 
179
		duration ) * payloadsize * 8 / 1000 / 1000);
139
}
180
}
140
181
141
int
182
int
Lines 143-153 Link Here
143
{
184
{
144
	long payloadsize, duration;
185
	long payloadsize, duration;
145
	struct addrinfo hints, *res, *res0;
186
	struct addrinfo hints, *res, *res0;
146
	char *dummy, *packet;
187
	char *dummy;
147
	int port, s, error;
188
	u_char *packet;
189
	int family, port, s, error, nthreads = 1;
190
	struct td_desc **tp;	
148
	const char *cause = NULL;
191
	const char *cause = NULL;
192
	struct timespec starttime, tmptime;
193
	struct itimerval it;
149
194
150
	if (argc != 5)
195
	if (argc < 5)
151
		usage();
196
		usage();
152
197
153
	memset(&hints, 0, sizeof(hints));
198
	memset(&hints, 0, sizeof(hints));
Lines 177-182 Link Here
177
		/*NOTREACHED*/
222
		/*NOTREACHED*/
178
	}
223
	}
179
224
225
	if (argc > 5)
226
        nthreads = strtoul(argv[5], &dummy, 10);
227
    if (nthreads < 1 || nthreads > 64)
228
        usage();
229
180
	packet = malloc(payloadsize);
230
	packet = malloc(payloadsize);
181
	if (packet == NULL) {
231
	if (packet == NULL) {
182
		perror("malloc");
232
		perror("malloc");
Lines 213-221 Link Here
213
		return (-1);
263
		return (-1);
214
		/*NOTREACHED*/
264
		/*NOTREACHED*/
215
	}
265
	}
216
266
	family=res->ai_family;
217
	freeaddrinfo(res0);
267
	freeaddrinfo(res0);
218
268
219
	return (blast_loop(s, duration, packet, payloadsize));
269
	printf("netblast %d threads sending on UDP port %d\n",
270
    nthreads, (u_short)port);
271
272
	/*
273
	 * Begin by recording time information stats.
274
	 * Set the interval timer for when we want to wake up.
275
	 * SIGALRM will set a flag indicating it's time to stop.  Note that there's
276
	 * some overhead to the signal and timer setup, so the smaller the duration,
277
	 * the higher the relative overhead.
278
	 */
279
280
	if (signal(SIGALRM, signal_handler) == SIG_ERR) {
281
		perror("signal");
282
		return (-1);
283
	}
284
285
	if (clock_getres(CLOCK_REALTIME, &tmptime) == -1) {
286
		perror("clock_getres");
287
		return (-1);
288
	}
289
290
	if (clock_gettime(CLOCK_REALTIME, &starttime) == -1) {
291
		perror("clock_gettime");
292
		return (-1);
293
	}
294
295
	it.it_interval.tv_sec = 0;
296
	it.it_interval.tv_usec = 0;
297
	it.it_value.tv_sec = duration;
298
	it.it_value.tv_usec = 0;
299
300
	if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
301
		perror("setitimer");
302
		return (-1);
303
	}
304
305
    tp = make_threads(s, packet, payloadsize, nthreads);
306
    main_thread(tp, duration, starttime,  tmptime, payloadsize, family, nthreads);
220
307
221
}
308
}

Return to bug 179085