Skip to content

Commit

Permalink
Support for UDP Data-port that is different than the Control-port
Browse files Browse the repository at this point in the history
  • Loading branch information
davidBar-On committed Oct 23, 2024
1 parent 062ad48 commit e8da231
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/iperf.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ struct iperf_test
TAILQ_HEAD(xbind_addrhead, xbind_entry) xbind_addrs; /* all -X opts */
int bind_port; /* --cport option */
int server_port;
int data_port; /* from --port option */
int omit; /* duration of omit period (-O flag) */
int duration; /* total duration of test (-t flag) */
char *diskfile_name; /* -F option */
Expand Down
55 changes: 46 additions & 9 deletions src/iperf_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ iperf_get_test_server_port(struct iperf_test *ipt)
return ipt->server_port;
}

int
iperf_get_test_data_port(struct iperf_test *ipt)
{
return ipt->data_port;
}

char*
iperf_get_test_server_hostname(struct iperf_test *ipt)
{
Expand Down Expand Up @@ -566,6 +572,12 @@ iperf_set_test_server_port(struct iperf_test *ipt, int srv_port)
ipt->server_port = srv_port;
}

void
iperf_set_test_data_port(struct iperf_test *ipt, int srv_data_port)
{
ipt->data_port = srv_data_port;
}

void
iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize)
{
Expand Down Expand Up @@ -956,10 +968,10 @@ iperf_on_connect(struct iperf_test *test)
iperf_printf(test, report_time, now_str);

if (test->role == 'c') {
if (test->json_output)
cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s port: %d", test->server_hostname, (int64_t) test->server_port));
else {
iperf_printf(test, report_connecting, test->server_hostname, test->server_port);
if (test->json_output) {
cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s port: %d data-port: %d", test->server_hostname, (int64_t) test->server_port, (int64_t) test->data_port));
} else {
iperf_printf(test, report_connecting, test->server_hostname, test->server_port, test->data_port);
if (test->reverse)
iperf_printf(test, report_reverse, test->server_hostname);
}
Expand Down Expand Up @@ -1177,12 +1189,27 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
switch (flag) {
case 'p':
portno = atoi(optarg);
if (portno < 1 || portno > 65535) {
i_errno = IEBADPORT;
return -1;

slash = strchr(optarg, '/');
if (slash) { // Get Data port
*slash = '\0';
++slash;
portno = atoi(slash);
if (portno < 1 || portno > 65535) {
i_errno = IEBADPORT;
return -1;
}
test->data_port = portno;
client_flag = 1;
}
test->server_port = portno;
if (strlen(optarg) > 0) { // Get control (and data) port
portno = atoi(optarg);
if (portno < 1 || portno > 65535) {
i_errno = IEBADPORT;
return -1;
}
test->server_port = portno;
}
break;
case 'f':
if (!optarg) {
Expand Down Expand Up @@ -1772,6 +1799,11 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
if (!rate_flag)
test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0;

if (test->data_port != test->server_port && test->protocol->id != Pudp) {
i_errno = IEDATAPORT;
return -1;
}

/* if no bytes or blocks specified, nor a duration_flag, and we have -F,
** get the file-size as the bytes count to be transferred
*/
Expand Down Expand Up @@ -2288,6 +2320,8 @@ send_parameters(struct iperf_test *test)
cJSON_AddNumberToObject(j, "time", test->duration);
cJSON_AddNumberToObject(j, "num", test->settings->bytes);
cJSON_AddNumberToObject(j, "blockcount", test->settings->blocks);
if (test->protocol->id == Pudp)
cJSON_AddNumberToObject(j, "data_port", test->data_port);
if (test->settings->mss)
cJSON_AddNumberToObject(j, "MSS", test->settings->mss);
if (test->no_delay)
Expand Down Expand Up @@ -2403,6 +2437,8 @@ get_parameters(struct iperf_test *test)
test->settings->blocks = 0;
if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL)
test->settings->blocks = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "data_port")) != NULL)
test->data_port = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL)
test->settings->mss = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL)
Expand Down Expand Up @@ -3025,6 +3061,7 @@ iperf_defaults(struct iperf_test *testp)
testp->congestion_used = NULL;
testp->remote_congestion_used = NULL;
testp->server_port = PORT;
testp->data_port = testp->server_port;
testp->ctrl_sck = -1;
testp->listener = -1;
testp->prot_listener = -1;
Expand Down
1 change: 1 addition & 0 deletions src/iperf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ enum {
IESNDTIMEOUT = 33, // Illegal message send timeout
IEUDPFILETRANSFER = 34, // Cannot transfer file using UDP
IESERVERAUTHUSERS = 35, // Cannot access authorized users file
IEDATAPORT = 36, // Data port is supported only for UDP
/* Test errors */
IENEWTEST = 100, // Unable to create a new test (check perror)
IEINITTEST = 101, // Test initialization failed (check perror)
Expand Down
5 changes: 4 additions & 1 deletion src/iperf_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,10 @@ iperf_strerror(int int_errno)
snprintf(errstr, len, "bad format specifier (valid formats are in the set [kmgtKMGT])");
break;
case IEBADPORT:
snprintf(errstr, len, "port number must be between 1 and 65535 inclusive");
snprintf(errstr, len, "illegal port value, number must be between 1 and 65535 inclusive");
break;
case IEDATAPORT:
snprintf(errstr, len, "data port is supported only for UDP");
break;
case IEMSS:
snprintf(errstr, len, "TCP MSS too large (maximum = %d bytes)", MAX_MSS);
Expand Down
5 changes: 3 additions & 2 deletions src/iperf_locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ const char usage_shortstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" iperf3 [-h|--help] [-v|--version]\n\n"
"Server or Client:\n"
" -p, --port # server port to listen on/connect to\n"
" -p, --port #[/#] server port to listen on/connect to\n"
" (optional Client only - port for UDP data send/receive)\n"
" -f, --format [kmgtKMGT] format to report: Kbits, Mbits, Gbits, Tbits\n"
" -i, --interval # seconds between periodic throughput reports\n"
" -I, --pidfile file write PID file\n"
Expand Down Expand Up @@ -311,7 +312,7 @@ const char report_time[] =
"Time: %s\n";

const char report_connecting[] =
"Connecting to host %s, port %d\n";
"Connecting to host %s, port %d, data-port %d\n";

const char report_authentication_succeeded[] =
"Authentication succeeded for user '%s' ts %" PRIu64 "\n";
Expand Down
6 changes: 3 additions & 3 deletions src/iperf_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ iperf_udp_accept(struct iperf_test *test)
* Create a new "listening" socket to replace the one we were using before.
*/
FD_CLR(test->prot_listener, &test->read_set); // No control messages from old listener
test->prot_listener = netannounce(test->settings->domain, Pudp, test->bind_address, test->bind_dev, test->server_port);
test->prot_listener = netannounce(test->settings->domain, Pudp, test->bind_address, test->bind_dev, test->data_port);
if (test->prot_listener < 0) {
i_errno = IESTREAMLISTEN;
return -1;
Expand Down Expand Up @@ -479,7 +479,7 @@ iperf_udp_listen(struct iperf_test *test)
{
int s;

if ((s = netannounce(test->settings->domain, Pudp, test->bind_address, test->bind_dev, test->server_port)) < 0) {
if ((s = netannounce(test->settings->domain, Pudp, test->bind_address, test->bind_dev, test->data_port)) < 0) {
i_errno = IESTREAMLISTEN;
return -1;
}
Expand Down Expand Up @@ -508,7 +508,7 @@ iperf_udp_connect(struct iperf_test *test)
int i, max_len_wait_for_reply;

/* Create and bind our local socket. */
if ((s = netdial(test->settings->domain, Pudp, test->bind_address, test->bind_dev, test->bind_port, test->server_hostname, test->server_port, -1)) < 0) {
if ((s = netdial(test->settings->domain, Pudp, test->bind_address, test->bind_dev, test->bind_port, test->server_hostname, test->data_port, -1)) < 0) {
i_errno = IESTREAMCONNECT;
return -1;
}
Expand Down

0 comments on commit e8da231

Please sign in to comment.