2
* Copyright (C) 2008 Sun Microsystems
4
* This file is part of uperf.
6
* uperf is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 3
8
* as published by the Free Software Foundation.
10
* uperf is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with uperf. If not, see http://www.gnu.org/licenses/.
20
* Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is
21
* subject to license terms.
25
#include "../config.h"
26
#endif /* HAVE_CONFIG_H */
29
#endif /* HAVE_STRING_H */
36
#include <sys/types.h>
37
#include <sys/socket.h>
39
#include <netinet/in.h>
40
#include <netinet/tcp.h>
41
#include <arpa/inet.h>
44
#include <sys/types.h>
47
#include <sys/socket.h>
48
#include <arpa/inet.h>
50
#ifdef HAVE_SYS_POLL_H
52
#endif /* HAVE_SYS_POLL_H */
57
#include "workorder.h"
60
#define USE_POLL_ACCEPT 1
61
#define LISTENQ 10240 /* 2nd argument to listen() */
62
#define TIMEOUT 1200000 /* Argument to poll */
65
name_to_addr(const char *address, struct sockaddr_storage *saddr)
67
struct addrinfo *res, *res0, hints;
70
memset(&hints, 0, sizeof(hints));
71
hints.ai_family = PF_UNSPEC;
72
hints.ai_socktype = SOCK_STREAM;
73
if ((error = getaddrinfo(address, NULL, NULL, &res0)) == 0) {
74
for (res = res0; res; res = res->ai_next) {
75
if ((res->ai_addr->sa_family != AF_INET) &&
76
(res->ai_addr->sa_family != AF_INET6)) {
79
memcpy(saddr, res->ai_addr, res->ai_addrlen);
84
return (UPERF_SUCCESS);
86
return (UPERF_FAILURE);
89
ulog_err("name_to_addr(%s): %s\n", address, gai_strerror(error));
90
return (UPERF_FAILURE);
95
generic_socket(protocol_t *p, int domain, int protocol)
97
if ((p->fd = socket(domain, SOCK_STREAM, protocol)) < 0) {
98
ulog_err("%s: Cannot create socket", protocol_to_str(p->type));
99
return (UPERF_FAILURE);
101
return (UPERF_SUCCESS);
106
generic_connect(protocol_t *p, int protocol)
108
struct sockaddr_storage serv;
112
uperf_debug("Connecting to %s:%d\n", p->host, p->port);
114
(void) memset(&serv, 0, sizeof(struct sockaddr_storage));
115
if (name_to_addr(p->host, &serv)) {
116
/* Error is already reported by name_to_addr, so just return */
117
return (UPERF_FAILURE);
120
if (generic_socket(p, serv.ss_family, protocol) < 0) {
121
return (UPERF_FAILURE);
123
switch (serv.ss_family) {
125
((struct sockaddr_in *)&serv)->sin_port = htons(p->port);
126
len = (socklen_t)sizeof(struct sockaddr_in);
129
((struct sockaddr_in6 *)&serv)->sin6_port = htons(p->port);
130
len = (socklen_t)sizeof(struct sockaddr_in6);
131
if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(int)) < 0) {
132
return (UPERF_FAILURE);
136
uperf_debug("Unsupported protocol family: %d\n", serv.ss_family);
137
return (UPERF_FAILURE);
140
if (connect(p->fd, (const struct sockaddr *)&serv, len) < 0) {
141
ulog_err("%s: Cannot connect to %s:%d",
142
protocol_to_str(p->type), p->host, p->port);
143
return (UPERF_FAILURE);
146
return (UPERF_SUCCESS);
150
generic_setfd_nonblock(int fd)
152
return (fcntl(fd, F_SETFL, O_NONBLOCK));
156
generic_set_socket_buffer(int fd, int size)
161
return (UPERF_SUCCESS);
162
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&w, sizeof (w))) {
163
ulog_warn("Cannot set SO_SNDBUF");
165
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&w, sizeof (w))
167
ulog_warn(" Cannot set SO_RCVBUF");
170
return (UPERF_SUCCESS);
174
generic_verify_socket_buffer(int fd, int wndsz)
181
return (UPERF_SUCCESS);
184
len = sizeof (wndsz);
186
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&nwsz, &len) != 0) {
187
ulog_warn("Cannot get SO_SNDBUF");
189
diff = 1.0*nwsz/wndsz;
190
if (diff < 0.9 || diff > 1.1) {
191
ulog_warn("%s: %.2fKB (Requested:%.2fKB)",
192
"Send buffer", nwsz/1024.0, wndsz/1024.0);
194
uperf_info("Set Send buffer size to %.2fKB\n", nwsz/1024.0);
197
len = sizeof (wndsz);
198
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&nwsz, &len) != 0) {
199
ulog_warn("Cannot get SO_RCVBUF");
202
diff = 1.0*nwsz/wndsz;
203
if (diff < 0.9 || diff > 1.1) {
204
ulog_warn("%s: %.2fKB (Requested:%.2fKB)",
205
"Recv buffer", nwsz/1024.0, wndsz/1024.0);
207
uperf_info("Set Recv buffer size to %.2fKB\n", nwsz/1024.0);
210
return (UPERF_SUCCESS);
215
generic_listen(protocol_t *p, int pflag, void* options)
222
if (setsockopt(p->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) {
223
ulog_err("%s: Cannot set SO_REUSEADDR",
224
protocol_to_str(p->type));
226
if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(int)) < 0) {
231
if (use_ipv6_socket) {
232
struct sockaddr_in6 sin6;
234
memset(&sin6, 0, sizeof(struct sockaddr_in6));
235
sin6.sin6_family = AF_INET6;
236
sin6.sin6_port = htons(p->port);
237
sin6.sin6_addr = in6addr_any;
238
if (bind(p->fd, (const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6)) < 0) {
239
ulog_err("%s: Cannot bind to port %d",
240
protocol_to_str(p->type), p->port);
241
return (UPERF_FAILURE);
243
if (p->port == ANY_PORT) {
244
memset(&sin6, 0, sizeof(struct sockaddr_in6));
245
len = (socklen_t)sizeof(struct sockaddr_in6);
246
if ((getsockname(p->fd, (struct sockaddr *)&sin6, &len)) < 0) {
247
ulog_err("%s: Cannot getsockname",
248
protocol_to_str(p->type));
249
return (UPERF_FAILURE);
251
p->port = ntohs(sin6.sin6_port);
256
struct sockaddr_in sin;
258
memset(&sin, 0, sizeof(struct sockaddr_in));
259
sin.sin_family = AF_INET;
260
sin.sin_port = htons(p->port);
261
sin.sin_addr.s_addr = htonl(INADDR_ANY);
262
if (bind(p->fd, (const struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) {
263
ulog_err("%s: Cannot bind to port %d",
264
protocol_to_str(p->type), p->port);
265
return (UPERF_FAILURE);
267
if (p->port == ANY_PORT) {
268
memset(&sin, 0, sizeof(struct sockaddr_in));
269
len = (socklen_t)sizeof(struct sockaddr_in);
270
if ((getsockname(p->fd, (struct sockaddr *)&sin, &len)) < 0) {
271
ulog_err("%s: Cannot getsockname",
272
protocol_to_str(p->type));
273
return (UPERF_FAILURE);
275
p->port = ntohs(sin.sin_port);
280
listen(p->fd, LISTENQ);
281
uperf_debug("Listening on port %d\n", p->port);
287
* On success, a non negative value is returned. 0 is returned to
288
* indicate timeout. timeout is in millisecs
291
generic_poll(int fd, int timeout, short poll_type)
293
struct pollfd pfd[2];
299
pfd[0].events = poll_type;
302
return (poll(pfd, 1, timeout));
306
generic_disconnect(protocol_t *p)
308
if (p && p->fd >= 0) {
313
return (UPERF_SUCCESS);
317
generic_read(protocol_t *p, void *buffer, int size, void *options)
319
flowop_options_t *fo = (flowop_options_t *)options;
320
int timeout = (fo ? fo->poll_timeout/1.0e+6 : 0);
323
if ((generic_poll(p->fd, timeout, POLLIN)) <= 0)
326
return (read(p->fd, buffer, size));
331
generic_write(protocol_t *p, void *buffer, int size, void *options)
333
return (write(p->fd, buffer, size));
338
generic_recv(protocol_t *p, void *buffer, int size, void *options)
340
return (recv(p->fd, buffer, size, 0));
345
generic_send(protocol_t *p, void *buffer, int size, void *options)
347
return (send(p->fd, buffer, size, 0));
353
generic_undefined(protocol_t *p, void *options)
355
uperf_error("Undefined function in protocol called\n");
356
return (UPERF_FAILURE);
361
generic_accept(protocol_t *oldp, protocol_t *newp, void *options)
365
char hostname[NI_MAXHOST];
366
struct sockaddr_storage remote;
371
addrlen = (socklen_t)sizeof(struct sockaddr_storage);
374
if ((generic_poll(oldp->fd, timeout, POLLIN)) <= 0)
377
if ((newp->fd = accept(oldp->fd, (struct sockaddr *)&remote,
380
return (UPERF_FAILURE);
382
switch (remote.ss_family) {
385
struct sockaddr_in *sin;
387
sin = (struct sockaddr_in *)&remote;
388
inet_ntop(AF_INET, &sin->sin_addr, hostname, sizeof(hostname));
389
newp->port = ntohs(sin->sin_port);
394
struct sockaddr_in6 *sin6;
396
sin6 = (struct sockaddr_in6 *)&remote;
397
inet_ntop(AF_INET6, &sin6->sin6_addr, hostname, sizeof(hostname));
398
newp->port = ntohs(sin6->sin6_port);
402
return (UPERF_FAILURE);
405
(void) strlcpy(newp->host, hostname, sizeof(newp->host));
406
uperf_info("Accepted connection from %s:%d\n", newp->host, newp->port);
409
if ((error = getnameinfo((const struct sockaddr *)&remote, addrlen,
410
hostname, sizeof(hostname), NULL, 0, 0)) == 0) {
411
if (remote.ss_family == AF_INET) {
412
newp->port = ntohs(((struct sockaddr_in *)&remote)->sin_port);
414
newp->port = ntohs(((struct sockaddr_in6 *)&remote)->sin6_port);
416
(void) strlcpy(newp->host, hostname, MAXHOSTNAME);
417
uperf_info("Accepted connection from %s:%d\n",
418
newp->host, newp->port);
421
(void) snprintf(msg, sizeof (msg),
422
"getnameinfo failed after accept: %s", gai_strerror(error));
423
uperf_log_msg(UPERF_LOG_ERROR, errno, msg);
427
return (UPERF_SUCCESS);
431
generic_fini(protocol_t *p)
440
set_tcp_options(int fd, flowop_options_t *f)
443
* It is necessary that we set the send and recv buffer
444
* sizes *before* connect() and bind(), else it will
447
* We also need to make sure that we verify the buffer
448
* sizes after the connect and listen
454
* We used to se buffer size to 1M in the past
455
* But on GNU/linux if you do not set the window
456
* size, it autotunes.
462
(void) generic_set_socket_buffer(fd, wndsz);
463
(void) generic_verify_socket_buffer(fd, wndsz);
465
if (f && (FO_TCP_NODELAY(f))) {
467
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
468
(char *)&nodelay, sizeof (nodelay))) {
469
ulog_warn("Cannot set TCP_NODELAY");