Skip to content

Commit 35031b2

Browse files
committed
NetMeter: Added the ability to set the TCP window size
Signed-off-by: Leonid Bloch <leonid@daynix.com>
1 parent 770639c commit 35031b2

File tree

3 files changed

+40
-21
lines changed

3 files changed

+40
-21
lines changed

NetMeter.py

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,13 @@ def yes_and_no(y, n):
223223
return 0
224224

225225

226+
def gen_tcp_win_msg(tcpwin):
227+
if tcpwin:
228+
return ', w=' + str(tcpwin)
229+
else:
230+
return ''
231+
232+
226233
def dir_prep(d):
227234
if not isdir(d):
228235
try:
@@ -309,12 +316,13 @@ def place_images(direction, protocol, summary_img, image_list, print_unit,
309316

310317
def gen_html(title, one2two_summary, two2one_summary, one2two_images, two2one_images, html_outname,
311318
protocol, streams, all_one2two_failed, all_two2one_failed, print_unit, localpart,
312-
cl1_pretty_name, cl2_pretty_name):
319+
cl1_pretty_name, cl2_pretty_name, tcpwin):
313320
if localpart:
314321
CPU_note = 'and CPU '
315322
else:
316323
CPU_note = ''
317324

325+
tcp_win_msg = gen_tcp_win_msg(tcpwin)
318326
content = (
319327
'<!doctype html>\n'
320328
'<html>\n'
@@ -391,7 +399,7 @@ def gen_html(title, one2two_summary, two2one_summary, one2two_images, two2one_im
391399
'<body>\n'
392400
'<div id="header">\n'
393401
)
394-
content += (' <h3>' + title + ' [' + protocol + ', ' + str(streams) + ' st.]</h3>\n'
402+
content += (' <h3>' + title + ' [' + protocol + ', ' + str(streams) + ' st.' + tcp_win_msg + ']</h3>\n'
395403
'</div>\n'
396404
'<div id="container">\n'
397405
)
@@ -623,7 +631,7 @@ def plot_iperf_data(passed, plot_type, net_dat_file):
623631
def write_gp(gp_outname, net_dat_file, proc_dat_file, img_file, net_rate,
624632
protocol, streams, print_unit, cl1_pretty_name, cl2_pretty_name,
625633
plot_type = 'singlesize', direction = 'one2two', finished = True,
626-
server_fault = False, packet_size = 0.0):
634+
server_fault = False, packet_size = 0.0, tcpwin = None):
627635
try:
628636
net_rate, rate_units, rate_factor = get_size_units_factor(net_rate, rate=True)
629637
rate_format = ''
@@ -678,6 +686,7 @@ def write_gp(gp_outname, net_dat_file, proc_dat_file, img_file, net_rate,
678686
y2_axis = ''
679687
rmargin = 'set rmargin 4.5\n'
680688

689+
tcp_win_msg = gen_tcp_win_msg(tcpwin)
681690
warning_message = ''
682691
if not finished:
683692
warning_message = 'set label "Warning:\\nTest failed to finish!\\nResults may not be accurate!" at screen 0.01, screen 0.96 tc rgb "red"\n'
@@ -691,7 +700,7 @@ def write_gp(gp_outname, net_dat_file, proc_dat_file, img_file, net_rate,
691700
'set terminal pngcairo nocrop enhanced size 1024,768 font "Verdana,15"\n'
692701
'set output "' + img_file + '"\n'
693702
'\n'
694-
'set title "{/=20 ' + plot_title + '}\\n\\n{/=18 (' + plot_subtitle + ', ' + protocol + ', ' + str(streams) + ' st.)}"\n'
703+
'set title "{/=20 ' + plot_title + '}\\n\\n{/=18 (' + plot_subtitle + ', ' + protocol + ', ' + str(streams) + ' st.' + tcp_win_msg + ')}"\n'
695704
+ rate_format + warning_message +
696705
'\n'
697706
'set xlabel "' + x_title + '"\n'
@@ -712,8 +721,10 @@ def write_gp(gp_outname, net_dat_file, proc_dat_file, img_file, net_rate,
712721
outfile.write(content)
713722

714723

715-
def set_protocol_opts(protocol, client = True):
716-
if protocol == 'TCP':
724+
def set_protocol_opts(protocol, tcpwin, client = True):
725+
if protocol == 'TCP' and tcpwin:
726+
return ['-w', str(tcpwin)]
727+
elif protocol == 'TCP':
717728
return []
718729
elif protocol == 'UDP':
719730
if client:
@@ -736,9 +747,9 @@ def bend_max_size(size, protocol):
736747
return size
737748

738749

739-
def run_server(protocol, init_name, dir_time, conn):
750+
def run_server(protocol, init_name, dir_time, conn, tcpwin):
740751
iperf_args = ['-s', '-i', '10', '-y', 'C']
741-
protocol_opts = set_protocol_opts(protocol, client = False)
752+
protocol_opts = set_protocol_opts(protocol, tcpwin, client = False)
742753
iperf_args += protocol_opts
743754
conn_name = conn.getname()
744755
iperf_command, output = conn.get_command(iperf_args, init_name + '_iperf.dat', init_name + '_iperf.err')
@@ -749,15 +760,15 @@ def run_server(protocol, init_name, dir_time, conn):
749760

750761

751762
def run_client(server_addr, runtime, p_size, streams, init_name, dir_time,
752-
protocol, conn, localpart):
763+
protocol, conn, localpart, tcpwin):
753764
p_size = bend_max_size(p_size, protocol)
754765
repetitions, mod = divmod(runtime, 10)
755766
if not mod:
756767
runtime += 1
757768

758769
iperf_args = ['-c', server_addr, '-t', str(runtime), '-l', str(p_size),
759770
'-P', str(streams)]
760-
protocol_opts = set_protocol_opts(protocol)
771+
protocol_opts = set_protocol_opts(protocol, tcpwin)
761772
iperf_args += protocol_opts
762773
iperf_command, output = conn.get_command(iperf_args, init_name + '_iperf_client.out', init_name + '_iperf_client.err')
763774
source_name = conn.getname()
@@ -813,7 +824,7 @@ def stop_server(conn, dir_time):
813824

814825

815826
def run_tests(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip, runtime, p_sizes,
816-
streams, timestamp, test_title, protocol, export_dir):
827+
streams, timestamp, test_title, protocol, tcpwin, export_dir):
817828
series_time = str(timedelta(seconds = 2 * len(p_sizes) * (runtime + 30) + 20))
818829
print(time_header() + '\033[92mStarting ' + protocol + ' tests.\033[0m Expected run time: ' + series_time)
819830
top_dir_name = timestamp + '_' + protocol + '_' + str(streams) + '_st'
@@ -851,10 +862,10 @@ def run_tests(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip, runtime, p_sizes,
851862
combined_sumname = dir_time + '_' + direction + '_summary'
852863
try:
853864
print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
854-
run_server(protocol, init_name, dir_time, server_conn)
865+
run_server(protocol, init_name, dir_time, server_conn, tcpwin)
855866
test_completed, repetitions = run_client(server_addr, runtime, p, streams,
856867
init_name, dir_time, protocol,
857-
client_conn, localpart)
868+
client_conn, localpart, tcpwin)
858869
stop_server(server_conn, dir_time)
859870
print('Parsing results...')
860871
if localpart:
@@ -886,7 +897,8 @@ def run_tests(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip, runtime, p_sizes,
886897
mpstat_single_file, basename(init_name + '.png'),
887898
tot_iperf_mean, protocol, streams, print_unit, cl1_pretty_name,
888899
cl2_pretty_name, plot_type = 'singlesize', direction = direction,
889-
finished = test_completed, server_fault = server_fault, packet_size = p)
900+
finished = test_completed, server_fault = server_fault,
901+
packet_size = p, tcpwin = tcpwin)
890902
print('Plotting...')
891903
pr = Popen([gnuplot_bin, basename(init_name + '.plt')], cwd=dirname(dir_time))
892904
pr.wait()
@@ -916,7 +928,8 @@ def run_tests(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip, runtime, p_sizes,
916928
mpstat_ser_file, basename(combined_sumname + '.png'),
917929
tot_iperf_mean, protocol, streams, print_unit, cl1_pretty_name,
918930
cl2_pretty_name, plot_type = 'multisize', direction = direction,
919-
server_fault = np.array(iperf_tot)[:,0], packet_size = np.mean(p_sizes))
931+
server_fault = np.array(iperf_tot)[:,0], packet_size = np.mean(p_sizes),
932+
tcpwin = tcpwin)
920933
pr = Popen([gnuplot_bin, basename(combined_sumname + '.plt')], cwd=dirname(dir_time))
921934
pr.wait()
922935
elif direction == 'one2two':
@@ -930,25 +943,26 @@ def run_tests(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip, runtime, p_sizes,
930943
join(raw_data_subdir, common_filename + '_two2one_summary.png'),
931944
one2two_images, two2one_images, html_name, protocol, streams,
932945
all_one2two_failed, all_two2one_failed, print_unit, localpart,
933-
cl1_pretty_name, cl2_pretty_name)
946+
cl1_pretty_name, cl2_pretty_name, tcpwin)
934947

935948

936949
def run_tests_for_protocols(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip,
937950
runtime, p_sizes, streams, timestamp, test_title,
938-
protocols, export_dir):
951+
protocols, tcpwin, export_dir):
939952
for p in protocols:
940953
run_tests(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip, runtime,
941-
p_sizes, streams, timestamp, test_title, p, export_dir)
954+
p_sizes, streams, timestamp, test_title, p, tcpwin,
955+
export_dir)
942956

943957

944958
def run_tests_for_streams(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip,
945959
runtime, p_sizes, streams, timestamp, test_title,
946-
protocols, export_dir):
960+
protocols, tcpwin, export_dir):
947961
for s in streams:
948962
if str(s).isdigit():
949963
run_tests_for_protocols(cl1_conn, cl2_conn, cl1_test_ip,
950964
cl2_test_ip, runtime, p_sizes, s,
951-
timestamp, test_title, protocols,
965+
timestamp, test_title, protocols, tcpwin,
952966
export_dir)
953967
else:
954968
print('\033[91mERROR:\033[0m Can not test for ' + s +
@@ -973,7 +987,7 @@ def run_tests_for_streams(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip,
973987
# Run tests
974988
run_tests_for_streams(cl1_conn, cl2_conn, cl1_test_ip, cl2_test_ip,
975989
run_duration, test_range, streams, rundate, title,
976-
protocols, export_dir)
990+
protocols, tcp_win_size, export_dir)
977991
# Shut down the clients if needed.
978992
# IF ONE OF THE CLIENTS IS LOCAL, IT WILL NOT SHUT DOWN.
979993
if shutdown:

NetMeterConfig.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
# The value MUST be one of 3: ['TCP'] | ['UDP'] | ['TCP', 'UDP']
5353
protocols = ['TCP', 'UDP']
5454

55+
# The desired TCP window size. [str or None].
56+
# Set to None for default. Example: '1M'.
57+
tcp_win_size = None
58+
5559
# Remote access method path: 'ssh' (for Linux), 'winexe' (for Windows),
5660
# or 'local' (to run on one of the clients). [str]
5761
# Note: for ssh access, an ssh key is required! The key needs to be unencrypted.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ These options are:
4343
* `run_duration`: [int] The duration of a single run, in seconds. Must be at least 20, preferable at least 120. (Example: `300`)
4444
* `streams`: [iterable] The desired number of streams to test. (Example: `[1, 4]`)
4545
* `protocols`: [iterable] The desired protocol(s). The value MUST be one of 3 possibilities: `['TCP']` | `['UDP']` | `['TCP', 'UDP']`.
46+
* `tcp_win_size`: [str or None] The desired TCP window size. Set to **None** for default. (Example: `'1M'`)
4647
* `access_method_cl[1|2]`: [string] The access method path: `'ssh'` for Linux, `'winexe'` for Windows, or `'local'`, if the client is the local machine (the command, or full path to it).
4748
* `ssh_port_cl[1|2]`: [string] SSH port on the client (needed only if the access is by SSH).
4849
* `creds`: [string] A path to the credentials file. (Example: `'creds.dat'`)

0 commit comments

Comments
 (0)