88
91
print(iperf_return)
89
match = re.search(r'\d+\s([GM])bits', iperf_return)
92
match = re.search(r'[\d\.]+\s([GM])bits', iperf_return)
91
94
throughput = match.group(0).split()[0]
92
95
units = match.group(1)
93
96
# self.iface.max_speed is always in mb/s, so we need to scale
94
97
# throughput to match
95
scaled_throughput = int(throughput)
98
scaled_throughput = float(throughput)
97
100
scaled_throughput *= 1000
99
102
scaled_throughput /= 1000
100
percent = scaled_throughput / int(self.iface.max_speed) * 100
101
print("Transfer speed: {} {}b/s".format(throughput, units))
104
percent = scaled_throughput / int(self.iface.max_speed) * 100
105
except (ZeroDivisionError, TypeError) as error:
106
# Catches a condition where the interface functions fine but
107
# ethtool fails to properly report max speed. In this case
108
# it's up to the reviewer to pass or fail.
109
logging.error("Max Speed was not reported properly. Run "
110
"ethtool and verify that the card is properly "
111
"reporting its capabilities.")
115
print("\nTransfer speed: {} {}b/s".format(throughput, units))
102
116
print("%3.2f%% of " % percent, end="")
103
print("theoretical max %sMb/s" % int(self.iface.max_speed))
118
print("theoretical max %sMb/s\n" % int(self.iface.max_speed))
119
except TypeError as error:
120
logging.error("Max Speed was not reported properly. Run "
121
"ethtool and verify that the card is properly "
122
"reporting its capabilities.")
125
if percent < self.fail_threshold:
106
126
logging.warn("Poor network performance detected")
281
class StressPerformanceTest:
283
def __init__(self, interface, target):
284
self.interface = interface
288
iperf_cmd = 'timeout 320 iperf -c {} -t 300'.format(self.target)
289
print("Running iperf...")
290
iperf = subprocess.Popen(shlex.split(iperf_cmd))
292
ping_cmd = 'ping -I {} {}'.format(self.interface, self.target)
293
ping = subprocess.Popen(shlex.split(ping_cmd), stdout=subprocess.PIPE)
297
(out, err) = ping.communicate()
299
if iperf.returncode != 0:
300
return iperf.returncode
302
print("Running ping test...")
304
time_re = re.compile('(?<=time=)[0-9]*')
305
for line in out.decode().split('\n'):
306
time = time_re.search(line)
308
if time and int(time.group()) > 2000:
310
print("ICMP packet was delayed by > 2000 ms.")
312
if 'unreachable' in line.lower():
261
319
class Interface(socket.socket):
263
321
Simple class that provides network interface information.
321
379
return self._read_data("device/label")
382
def get_test_parameters(args, environ, config_filename):
383
# Decide the actual values for test parameters, which can come
384
# from one of three possible sources: a config file, command-line
385
# arguments, or environment variables.
386
# - If command-line args were given, they take precedence
387
# - Next come environment variables, if set.
388
# - Last, values in the config file are used if present.
390
params = {"test_target_ftp": None,
393
"test_target_iperf": None}
395
#First (try to) load values from config file
396
config = configparser.SafeConfigParser()
399
with open(config_filename) as config_file:
400
config.readfp(config_file)
401
params["test_target_ftp"] = config.get("FTP", "Target")
402
params["test_user"] = config.get("FTP", "User")
403
params["test_pass"] = config.get("FTP", "Pass")
404
params["test_target_iperf"] = config.get("IPERF", "Target")
405
except FileNotFoundError as err:
406
pass # No biggie, we can still get configs from elsewhere
408
# Next see if we have environment variables to override the config file
409
# "partial" overrides are not allowed; if an env variable is missing,
410
# we won't use this at all.
411
if all([param.upper() in os.environ for param in params.keys()]):
412
for key in params.keys():
413
params[key] = os.environ[key.upper()]
415
# Finally, see if we have the command-line arguments that are the ultimate
416
# override. Again, we will only override if we have all of them.
417
if args.target and args.username and args.password:
418
params["test_target_ftp"] = args.target
419
params["test_user"] = args.username
420
params["test_pass"] = args.password
421
params["test_target_iperf"] = args.target
324
426
def interface_test(args):
325
427
if not "test_type" in vars(args):
430
# Determine whether to use the default or user-supplied config
432
DEFAULT_CFG = "/etc/checkbox.d/network.cfg"
433
if not "config" in vars(args):
434
config_filename = DEFAULT_CFG
436
config_filename = args.config
438
# Get the actual test data from one of three possible sources
439
test_parameters = get_test_parameters(args, os.environ, config_filename)
441
test_user = test_parameters["test_user"]
442
test_pass = test_parameters["test_pass"]
443
if (args.test_type.lower() == "iperf" or
444
args.test_type.lower() == "stress"):
445
test_target = test_parameters["test_target_iperf"]
447
test_target = test_parameters["test_target_ftp"]
449
# Validate that we got reasonable values
450
if "example.com" in test_target:
451
# Default values found in config file
452
logging.error("Please supply target via: %s", config_filename)
455
# Testing begins here!
328
457
# Check and make sure that interface is indeed connected
330
459
cmd = "ip link set dev %s up" % args.interface
336
465
# Give interface enough time to get DHCP address
339
# Open Network config file
340
DEFAULT_CFG = "/etc/checkbox.d/network.cfg"
341
if not "config" in vars(args):
342
config_file = DEFAULT_CFG
344
config_file = args.config
346
config = configparser.SafeConfigParser()
347
config.readfp(open(config_file))
349
# Set default network config options
350
test_target = args.target
351
test_user = args.username
352
test_pass = args.password
354
if test_target is None:
355
# Set FTP parameters based on config file
356
test_target = config.get("FTP", "Target")
357
test_user = config.get("FTP", "User")
358
test_pass = config.get("FTP", "Pass")
360
if args.test_type.lower() == "iperf":
361
test_target = config.get("IPERF", "Target")
363
if "example.com" in test_target:
364
# Default values found in config file
365
logging.error("Please supply target via: %s", config_file)
370
469
# Stop all other interfaces
371
470
extra_interfaces = \
392
491
result = ftp_benchmark.run()
394
493
elif args.test_type.lower() == "iperf":
395
iperf_benchmark = IPerfPerformanceTest(args.interface, test_target)
494
iperf_benchmark = IPerfPerformanceTest(args.interface, test_target,
396
496
result = iperf_benchmark.run()
498
elif args.test_type.lower() == "stress":
499
stress_benchmark = StressPerformanceTest(args.interface,
501
result = stress_benchmark.run()
398
503
for iface in extra_interfaces:
399
504
logging.debug("Restoring interface:%s", iface)
428
intro_message = "Network module\n\nThis script provides benchmarking " \
429
+ "and information for a specified network interface.\n\n\n" \
430
+ "Example NIC information usage:\nnetwork info -i eth0 --max-speed " \
431
+ "\n\nFor running ftp benchmark test: \nnetwork test -i eth0 -t ftp " \
432
+ "--target 192.168.0.1 --username USERID --password PASSW0RD " \
433
+ "--filesize-2\n\nPlease note that this script can use configuration " \
434
+ "values supplied via a config file.\nExample config file:\n[FTP]\n" \
435
+ "Target: 192.168.1.23\nUser: FTPUser\nPass:PassW0Rd\n" \
436
+ "[IPERF]\nTarget: 192.168.1.45\n**NOTE**\nDefault config location " \
437
+ "is /etc/checkbox.d/network.cfg"
537
This script provides benchmarking and information for a specified network
540
Example NIC information usage:
541
network info -i eth0 --max-speed
543
For running ftp benchmark test:
544
network test -i eth0 -t ftp
545
--target 192.168.0.1 --username USERID --password PASSW0RD
551
Configuration can be supplied in three different ways, with the following
554
1- Command-line parameters (see above).
555
2- Environment variables (example will follow).
556
3- Configuration file (example will follow).
557
Default config location is /etc/checkbox.d/network.cfg
559
Environment variables
560
=====================
561
ALL environment variables must be defined, even if empty, for them to be
562
picked up. The variables are:
440
582
parser = ArgumentParser(
441
583
description=intro_message, formatter_class=RawTextHelpFormatter)
451
593
test_parser.add_argument(
452
594
'-i', '--interface', type=str, required=True)
453
595
test_parser.add_argument(
454
'-t', '--test_type', type=str,
455
choices=("ftp", "iperf"), default="ftp",
596
'-t', '--test_type', type=str,
597
choices=("ftp", "iperf", "stress"), default="ftp",
456
598
help=("[FTP *Default*]"))
457
599
test_parser.add_argument('--target', type=str)
458
600
test_parser.add_argument(