@@ -364,6 +364,9 @@ iperf_connect(struct iperf_test *test)
364364{
365365 int opt ;
366366 socklen_t len ;
367+ #if defined(HAVE_TCP_KEEPALIVE )
368+ int kainterval , kacount ;
369+ #endif /* HAVE_TCP_KEEPALIVE */
367370
368371 if (NULL == test )
369372 {
@@ -391,11 +394,82 @@ iperf_connect(struct iperf_test *test)
391394 return -1 ;
392395 }
393396
397+ #if defined (HAVE_TCP_KEEPALIVE )
398+ // Set Control Connection TCP Keepalive (especially useful for long UDP test sessions)
399+ if (test -> settings -> cntl_ka ) {
400+ opt = 1 ;
401+ if (setsockopt (test -> ctrl_sck , SOL_SOCKET , SO_KEEPALIVE , (char * ) & opt , sizeof (opt ))) {
402+ i_errno = IESETCNTLKA ;
403+ return -1 ;
404+ }
405+
406+ if ((opt = test -> settings -> cntl_ka_keepidle )) {
407+ if (setsockopt (test -> ctrl_sck , IPPROTO_TCP , TCP_KEEPIDLE , (char * ) & opt , sizeof (opt ))) {
408+ i_errno = IESETCNTLKAKEEPIDLE ;
409+ return -1 ;
410+ }
411+ }
412+
413+ // Seems that at least in Windows WSL2, TCP keepalive retries inteval must be smaller
414+ // than keepalive interval. Otherwise, the keepalive message is sent only once.
415+ // To make sure issues will not impact the tests in case the keepalive period was set,
416+ // when possible it is made sure that the full keepalive retries interval is less
417+ // than the the keepalive period.
418+ if (test -> settings -> cntl_ka_keepidle ) {
419+ if ((kainterval = test -> settings -> cntl_ka_interval ) == 0 ) {
420+ len = sizeof (kainterval );
421+ if (getsockopt (test -> ctrl_sck , IPPROTO_TCP , TCP_KEEPINTVL , (char * ) & kainterval , & len )) {
422+ i_errno = IESETCNTLKAINTERVAL ;
423+ return -1 ;
424+ }
425+ }
426+ if ((kacount = test -> settings -> cntl_ka_count ) == 0 ) {
427+ len = sizeof (kacount );
428+ if (getsockopt (test -> ctrl_sck , IPPROTO_TCP , TCP_KEEPCNT , (char * ) & kacount , & len )) {
429+ i_errno = IESETCNTLKACOUNT ;
430+ return -1 ;
431+ }
432+ }
433+
434+ if (test -> settings -> cntl_ka_keepidle <= (kainterval * kacount )) {
435+ if (test -> settings -> cntl_ka_interval > 0 || test -> settings -> cntl_ka_count > 0 ) {
436+ i_errno = IECNTLKA ;
437+ return -1 ;
438+ }
439+ if (kacount > 0 ) {
440+ test -> settings -> cntl_ka_interval = ((test -> settings -> cntl_ka_keepidle - 1 ) / kacount );
441+ if (test -> settings -> cntl_ka_interval <= 0 ) {
442+ test -> settings -> cntl_ka_interval = 1 ;
443+ }
444+ }
445+ }
446+ }
447+
448+ if ((opt = test -> settings -> cntl_ka_interval )) {
449+ if (setsockopt (test -> ctrl_sck , IPPROTO_TCP , TCP_KEEPINTVL , (char * ) & opt , sizeof (opt ))) {
450+ i_errno = IESETCNTLKAINTERVAL ;
451+ return -1 ;
452+ }
453+ }
454+ if ((opt = test -> settings -> cntl_ka_count )) {
455+ if (setsockopt (test -> ctrl_sck , IPPROTO_TCP , TCP_KEEPCNT , (char * ) & opt , sizeof (opt ))) {
456+ i_errno = IESETCNTLKACOUNT ;
457+ return -1 ;
458+ }
459+ }
460+
461+ if (test -> verbose ) {
462+ printf ("Control connection TCP Keepalive TCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT set to %d/%d/%d (0 is system default)\n" ,
463+ test -> settings -> cntl_ka_keepidle , test -> settings -> cntl_ka_interval , test -> settings -> cntl_ka_count );
464+ }
465+ }
466+ #endif //HAVE_TCP_KEEPALIVE
467+
394468#if defined(HAVE_TCP_USER_TIMEOUT )
395469 if ((opt = test -> settings -> snd_timeout )) {
396470 if (setsockopt (test -> ctrl_sck , IPPROTO_TCP , TCP_USER_TIMEOUT , & opt , sizeof (opt )) < 0 ) {
397- i_errno = IESETUSERTIMEOUT ;
398- return -1 ;
471+ i_errno = IESETUSERTIMEOUT ;
472+ return -1 ;
399473 }
400474 }
401475#endif /* HAVE_TCP_USER_TIMEOUT */
0 commit comments