@@ -1188,6 +1188,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
11881188#endif /* HAVE_TCP_KEEPALIVE */
11891189#if defined(HAVE_IPPROTO_MPTCP )
11901190 {"mptcp" , no_argument , NULL , 'm' },
1191+ #endif
1192+ #if defined(HAVE_UDP_SEGMENT ) || defined (HAVE_UDP_GRO )
1193+ {"no-gsro" , no_argument , NULL , OPT_NO_GSRO },
11911194#endif
11921195 {"debug" , optional_argument , NULL , 'd' },
11931196 {"help" , no_argument , NULL , 'h' },
@@ -1781,6 +1784,17 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
17811784 set_protocol (test , Ptcp );
17821785 test -> mptcp = 1 ;
17831786 break ;
1787+ #endif
1788+ #if defined(HAVE_UDP_SEGMENT ) || defined(HAVE_UDP_GRO )
1789+ case OPT_NO_GSRO :
1790+ /* Disable GSO/GRO which would otherwise be enabled by default */
1791+ #ifdef HAVE_UDP_SEGMENT
1792+ test -> settings -> gso = 0 ;
1793+ #endif
1794+ #ifdef HAVE_UDP_GRO
1795+ test -> settings -> gro = 0 ;
1796+ #endif
1797+ break ;
17841798#endif
17851799 case 'h' :
17861800 usage_long (stdout );
@@ -1802,6 +1816,8 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
18021816 return -1 ;
18031817 }
18041818
1819+ /* GSO/GRO are enabled by default when available, disabled only via --no-gsro */
1820+
18051821#if defined(HAVE_SSL )
18061822
18071823 if (test -> role == 's' && (client_username || client_rsa_public_key )){
@@ -1906,6 +1922,20 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
19061922 i_errno = IEUDPBLOCKSIZE ;
19071923 return -1 ;
19081924 }
1925+
1926+ #ifdef HAVE_UDP_SEGMENT
1927+ if (test -> protocol -> id == Pudp && test -> settings -> gso ) {
1928+ test -> settings -> gso_dg_size = blksize ;
1929+ /* use the multiple of datagram size for the best efficiency. */
1930+ if (test -> settings -> gso_dg_size > 0 ) {
1931+ test -> settings -> gso_bf_size = (test -> settings -> gso_bf_size / test -> settings -> gso_dg_size ) * test -> settings -> gso_dg_size ;
1932+ } else {
1933+ /* If gso_dg_size is 0 (unlimited bandwidth), use default UDP datagram size */
1934+ test -> settings -> gso_dg_size = 1472 ; /* Standard UDP payload size for Ethernet MTU */
1935+ }
1936+ }
1937+ #endif
1938+
19091939 test -> settings -> blksize = blksize ;
19101940
19111941 if (!rate_flag )
@@ -2572,6 +2602,18 @@ get_parameters(struct iperf_test *test)
25722602 test -> settings -> socket_bufsize = j_p -> valueint ;
25732603 if ((j_p = iperf_cJSON_GetObjectItemType (j , "len" , cJSON_Number )) != NULL )
25742604 test -> settings -> blksize = j_p -> valueint ;
2605+ #ifdef HAVE_UDP_SEGMENT
2606+ if (test -> protocol -> id == Pudp && test -> settings -> gso == 1 ) {
2607+ test -> settings -> gso_dg_size = test -> settings -> blksize ;
2608+ /* use the multiple of datagram size for the best efficiency. */
2609+ if (test -> settings -> gso_dg_size > 0 ) {
2610+ test -> settings -> gso_bf_size = (test -> settings -> gso_bf_size / test -> settings -> gso_dg_size ) * test -> settings -> gso_dg_size ;
2611+ } else {
2612+ /* If gso_dg_size is 0 (unlimited bandwidth), use default UDP datagram size */
2613+ test -> settings -> gso_dg_size = 1472 ; /* Standard UDP payload size for Ethernet MTU */
2614+ }
2615+ }
2616+ #endif
25752617 if ((j_p = iperf_cJSON_GetObjectItemType (j , "bandwidth" , cJSON_Number )) != NULL )
25762618 test -> settings -> rate = j_p -> valueint ;
25772619 if ((j_p = iperf_cJSON_GetObjectItemType (j , "fqrate" , cJSON_Number )) != NULL )
@@ -3232,6 +3274,15 @@ iperf_defaults(struct iperf_test *testp)
32323274 testp -> settings -> fqrate = 0 ;
32333275 testp -> settings -> pacing_timer = DEFAULT_PACING_TIMER ;
32343276 testp -> settings -> burst = 0 ;
3277+ #ifdef HAVE_UDP_SEGMENT
3278+ testp -> settings -> gso = 1 ; /* Enable GSO by default */
3279+ testp -> settings -> gso_dg_size = 0 ;
3280+ testp -> settings -> gso_bf_size = GSO_BF_MAX_SIZE ;
3281+ #endif
3282+ #ifdef HAVE_UDP_GRO
3283+ testp -> settings -> gro = 1 ; /* Enable GRO by default */
3284+ testp -> settings -> gro_bf_size = GRO_BF_MAX_SIZE ;
3285+ #endif
32353286 testp -> settings -> mss = 0 ;
32363287 testp -> settings -> bytes = 0 ;
32373288 testp -> settings -> blocks = 0 ;
@@ -3545,6 +3596,13 @@ iperf_reset_test(struct iperf_test *test)
35453596 test -> settings -> burst = 0 ;
35463597 test -> settings -> mss = 0 ;
35473598 test -> settings -> tos = 0 ;
3599+ #ifdef HAVE_UDP_SEGMENT
3600+ test -> settings -> gso_dg_size = 0 ;
3601+ test -> settings -> gso_bf_size = GSO_BF_MAX_SIZE ;
3602+ #endif
3603+ #ifdef HAVE_UDP_GRO
3604+ test -> settings -> gro_bf_size = GRO_BF_MAX_SIZE ;
3605+ #endif
35483606 test -> settings -> dont_fragment = 0 ;
35493607 test -> zerocopy = 0 ;
35503608 test -> settings -> skip_rx_copy = 0 ;
@@ -4709,6 +4767,7 @@ iperf_new_stream(struct iperf_test *test, int s, int sender)
47094767{
47104768 struct iperf_stream * sp ;
47114769 int ret = 0 ;
4770+ int size ;
47124771
47134772 char template [1024 ];
47144773 if (test -> tmp_template ) {
@@ -4767,13 +4826,24 @@ iperf_new_stream(struct iperf_test *test, int s, int sender)
47674826 free (sp );
47684827 return NULL ;
47694828 }
4770- if (ftruncate (sp -> buffer_fd , test -> settings -> blksize ) < 0 ) {
4829+ size = test -> settings -> blksize ;
4830+ #ifdef HAVE_UDP_SEGMENT
4831+ if (test -> protocol -> id == Pudp && test -> settings -> gso && (size < test -> settings -> gso_bf_size ))
4832+ size = test -> settings -> gso_bf_size ;
4833+ #endif
4834+ #ifdef HAVE_UDP_GRO
4835+ if (test -> protocol -> id == Pudp && test -> settings -> gro && (size < test -> settings -> gro_bf_size ))
4836+ size = test -> settings -> gro_bf_size ;
4837+ #endif
4838+ if (sp -> test -> debug )
4839+ printf ("Buffer %d bytes\n" , size );
4840+ if (ftruncate (sp -> buffer_fd , size ) < 0 ) {
47714841 i_errno = IECREATESTREAM ;
47724842 free (sp -> result );
47734843 free (sp );
47744844 return NULL ;
47754845 }
4776- sp -> buffer = (char * ) mmap (NULL , test -> settings -> blksize , PROT_READ |PROT_WRITE , MAP_SHARED , sp -> buffer_fd , 0 );
4846+ sp -> buffer = (char * ) mmap (NULL , size , PROT_READ |PROT_WRITE , MAP_PRIVATE , sp -> buffer_fd , 0 );
47774847 if (sp -> buffer == MAP_FAILED ) {
47784848 i_errno = IECREATESTREAM ;
47794849 free (sp -> result );
0 commit comments