^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/usr/bin/env python3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # Program to allow users to fuzz test Hyper-V drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) # by interfacing with Hyper-V debugfs attributes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) # Current test methods available:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) # 1. delay testing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) # Current file/directory structure of hyper-V debugfs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) # /sys/kernel/debug/hyperv/UUID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) # /sys/kernel/debug/hyperv/UUID/<test-state filename>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) # /sys/kernel/debug/hyperv/UUID/<test-method sub-directory>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) # author: Branden Bonaby <brandonbonaby94@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) import cmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) import argparse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) import glob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) from argparse import RawDescriptionHelpFormatter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) from argparse import RawTextHelpFormatter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) from enum import Enum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) # Do not change unless, you change the debugfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) # in /drivers/hv/debugfs.c. All fuzz testing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) # attributes will start with "fuzz_test".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) # debugfs path for hyperv must exist before proceeding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) debugfs_hyperv_path = "/sys/kernel/debug/hyperv"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if not os.path.isdir(debugfs_hyperv_path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) print("{} doesn't exist/check permissions".format(debugfs_hyperv_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) class dev_state(Enum):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) off = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) on = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) # File names, that correspond to the files created in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) # /drivers/hv/debugfs.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) class f_names(Enum):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) state_f = "fuzz_test_state"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) buff_f = "fuzz_test_buffer_interrupt_delay"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) mess_f = "fuzz_test_message_delay"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) # Both single_actions and all_actions are used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) # for error checking and to allow for some subparser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) # names to be abbreviated. Do not abbreviate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) # test method names, as it will become less intuitive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) # as to what the user can do. If you do decide to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) # abbreviate the test method name, make sure the main
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) # function reflects this change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) all_actions = [
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) "disable_all",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) "enable_all",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) "view_all",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "V"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) single_actions = [
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) "disable_single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) "d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) "enable_single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) "view_single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) "v"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) def main():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) file_map = recursive_file_lookup(debugfs_hyperv_path, dict())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) args = parse_args()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (not args.action):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) print ("Error, no options selected...exiting")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) arg_set = { k for (k,v) in vars(args).items() if v and k != "action" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) arg_set.add(args.action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) path = args.path if "path" in arg_set else None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (path and path[-1] == "/"):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) path = path[:-1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) validate_args_path(path, arg_set, file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (path and "enable_single" in arg_set):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) state_path = locate_state(path, file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) set_test_state(state_path, dev_state.on.value, args.quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) # Use subparsers as the key for different actions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if ("delay" in arg_set):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) validate_delay_values(args.delay_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (args.enable_all):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) set_delay_all_devices(file_map, args.delay_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) args.quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) set_delay_values(path, file_map, args.delay_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) args.quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) elif ("disable_all" in arg_set or "D" in arg_set):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) disable_all_testing(file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) elif ("disable_single" in arg_set or "d" in arg_set):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) disable_testing_single_device(path, file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) elif ("view_all" in arg_set or "V" in arg_set):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) get_all_devices_test_status(file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) elif ("view_single" in arg_set or "v" in arg_set):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) get_device_test_values(path, file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) # Get the state location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) def locate_state(device, file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return file_map[device][f_names.state_f.value]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) # Validate delay values to make sure they are acceptable to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) # enable delays on a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) def validate_delay_values(delay):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (delay[0] == -1 and delay[1] == -1):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) print("\nError, At least 1 value must be greater than 0")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) for i in delay:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (i < -1 or i == 0 or i > 1000):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) print("\nError, Values must be equal to -1 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) "or be > 0 and <= 1000")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) # Validate argument path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) def validate_args_path(path, arg_set, file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (not path and any(element in arg_set for element in single_actions)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) print("Error, path (-p) REQUIRED for the specified option. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "Use (-h) to check usage.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) elif (path and any(item in arg_set for item in all_actions)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) print("Error, path (-p) NOT REQUIRED for the specified option. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) "Use (-h) to check usage." )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) elif (path not in file_map and any(item in arg_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) for item in single_actions)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) print("Error, path '{}' not a valid vmbus device".format(path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) # display Testing status of single device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) def get_device_test_values(path, file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) for name in file_map[path]:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) file_location = file_map[path][name]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) print( name + " = " + str(read_test_files(file_location)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) # Create a map of the vmbus devices and their associated files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) # [key=device, value = [key = filename, value = file path]]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) def recursive_file_lookup(path, file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for f_path in glob.iglob(path + '**/*'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (os.path.isfile(f_path)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (f_path.rsplit("/",2)[0] == debugfs_hyperv_path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) directory = f_path.rsplit("/",1)[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) directory = f_path.rsplit("/",2)[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) f_name = f_path.split("/")[-1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (file_map.get(directory)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) file_map[directory].update({f_name:f_path})
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) file_map[directory] = {f_name:f_path}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) elif (os.path.isdir(f_path)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) recursive_file_lookup(f_path,file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return file_map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) # display Testing state of devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) def get_all_devices_test_status(file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) for device in file_map:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (get_test_state(locate_state(device, file_map)) is 1):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) print("Testing = ON for: {}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .format(device.split("/")[5]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) print("Testing = OFF for: {}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .format(device.split("/")[5]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) # read the vmbus device files, path must be absolute path before calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) def read_test_files(path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) with open(path,"r") as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) file_value = f.readline().strip()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return int(file_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) except IOError as e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) errno, strerror = e.args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) print("I/O error({0}): {1} on file {2}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .format(errno, strerror, path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) except ValueError:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) print ("Element to int conversion error in: \n{}".format(path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) # writing to vmbus device files, path must be absolute path before calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) def write_test_files(path, value):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) with open(path,"w") as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) f.write("{}".format(value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) except IOError as e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) errno, strerror = e.args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) print("I/O error({0}): {1} on file {2}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .format(errno, strerror, path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) # set testing state of device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) def set_test_state(state_path, state_value, quiet):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) write_test_files(state_path, state_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (get_test_state(state_path) is 1):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (not quiet):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) print("Testing = ON for device: {}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .format(state_path.split("/")[5]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (not quiet):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) print("Testing = OFF for device: {}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .format(state_path.split("/")[5]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) # get testing state of device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) def get_test_state(state_path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #state == 1 - test = ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #state == 0 - test = OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return read_test_files(state_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) # write 1 - 1000 microseconds, into a single device using the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) # fuzz_test_buffer_interrupt_delay and fuzz_test_message_delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) # debugfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) def set_delay_values(device, file_map, delay_length, quiet):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) interrupt = file_map[device][f_names.buff_f.value]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) message = file_map[device][f_names.mess_f.value]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) # delay[0]- buffer interrupt delay, delay[1]- message delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (delay_length[0] >= 0 and delay_length[0] <= 1000):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) write_test_files(interrupt, delay_length[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (delay_length[1] >= 0 and delay_length[1] <= 1000):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) write_test_files(message, delay_length[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (not quiet):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) print("Buffer delay testing = {} for: {}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .format(read_test_files(interrupt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) interrupt.split("/")[5]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) print("Message delay testing = {} for: {}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .format(read_test_files(message),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) message.split("/")[5]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) except IOError as e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) errno, strerror = e.args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) print("I/O error({0}): {1} on files {2}{3}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .format(errno, strerror, interrupt, message))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) exit(-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) # enabling delay testing on all devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) def set_delay_all_devices(file_map, delay, quiet):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) for device in (file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) set_test_state(locate_state(device, file_map),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) dev_state.on.value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) set_delay_values(device, file_map, delay, quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) # disable all testing on a SINGLE device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) def disable_testing_single_device(device, file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) for name in file_map[device]:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) file_location = file_map[device][name]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) write_test_files(file_location, dev_state.off.value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) print("ALL testing now OFF for {}".format(device.split("/")[-1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) # disable all testing on ALL devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) def disable_all_testing(file_map):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) for device in file_map:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) disable_testing_single_device(device, file_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) def parse_args():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) parser = argparse.ArgumentParser(prog = "vmbus_testing",usage ="\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) "%(prog)s [delay] [-h] [-e|-E] -t [-p]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) "%(prog)s [view_all | V] [-h]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) "%(prog)s [disable_all | D] [-h]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) "%(prog)s [disable_single | d] [-h|-p]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) "%(prog)s [view_single | v] [-h|-p]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) "%(prog)s --version\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) description = "\nUse lsvmbus to get vmbus device type "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) "information.\n" "\nThe debugfs root path is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) "/sys/kernel/debug/hyperv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) formatter_class = RawDescriptionHelpFormatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) subparsers = parser.add_subparsers(dest = "action")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) parser.add_argument("--version", action = "version",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) version = '%(prog)s 0.1.0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) parser.add_argument("-q","--quiet", action = "store_true",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) help = "silence none important test messages."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) " This will only work when enabling testing"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) " on a device.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) # Use the path parser to hold the --path attribute so it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) # be shared between subparsers. Also do the same for the state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) # parser, as all testing methods will use --enable_all and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) # enable_single.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) path_parser = argparse.ArgumentParser(add_help=False)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) path_parser.add_argument("-p","--path", metavar = "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) help = "Debugfs path to a vmbus device. The path "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) "must be the absolute path to the device.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) state_parser = argparse.ArgumentParser(add_help=False)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) state_group = state_parser.add_mutually_exclusive_group(required = True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) state_group.add_argument("-E", "--enable_all", action = "store_const",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) const = "enable_all",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) help = "Enable the specified test type "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) "on ALL vmbus devices.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) state_group.add_argument("-e", "--enable_single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) action = "store_const",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) const = "enable_single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) help = "Enable the specified test type on a "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) "SINGLE vmbus device.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) parser_delay = subparsers.add_parser("delay",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) parents = [state_parser, path_parser],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) help = "Delay the ring buffer interrupt or the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) "ring buffer message reads in microseconds.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) prog = "vmbus_testing",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) usage = "%(prog)s [-h]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) "%(prog)s -E -t [value] [value]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) "%(prog)s -e -t [value] [value] -p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) description = "Delay the ring buffer interrupt for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) "vmbus devices, or delay the ring buffer message "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) "reads for vmbus devices (both in microseconds). This "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) "is only on the host to guest channel.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) parser_delay.add_argument("-t", "--delay_time", metavar = "", nargs = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) type = check_range, default =[0,0], required = (True),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) help = "Set [buffer] & [message] delay time. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) "Value constraints: -1 == value "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) "or 0 < value <= 1000.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) "Use -1 to keep the previous value for that delay "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) "type, or a value > 0 <= 1000 to change the delay "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) "time.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) parser_dis_all = subparsers.add_parser("disable_all",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) aliases = ['D'], prog = "vmbus_testing",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) usage = "%(prog)s [disable_all | D] -h\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) "%(prog)s [disable_all | D]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) help = "Disable ALL testing on ALL vmbus devices.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) description = "Disable ALL testing on ALL vmbus "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) "devices.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) parser_dis_single = subparsers.add_parser("disable_single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) aliases = ['d'],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) parents = [path_parser], prog = "vmbus_testing",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) usage = "%(prog)s [disable_single | d] -h\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) "%(prog)s [disable_single | d] -p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) help = "Disable ALL testing on a SINGLE vmbus device.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) description = "Disable ALL testing on a SINGLE vmbus "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) "device.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) parser_view_all = subparsers.add_parser("view_all", aliases = ['V'],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) help = "View the test state for ALL vmbus devices.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) prog = "vmbus_testing",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) usage = "%(prog)s [view_all | V] -h\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) "%(prog)s [view_all | V]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) description = "This shows the test state for ALL the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) "vmbus devices.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) parser_view_single = subparsers.add_parser("view_single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) aliases = ['v'],parents = [path_parser],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) help = "View the test values for a SINGLE vmbus "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) "device.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) description = "This shows the test values for a SINGLE "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) "vmbus device.", prog = "vmbus_testing",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) usage = "%(prog)s [view_single | v] -h\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) "%(prog)s [view_single | v] -p")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return parser.parse_args()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) # value checking for range checking input in parser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) def check_range(arg1):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) val = int(arg1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) except ValueError as err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) raise argparse.ArgumentTypeError(str(err))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if val < -1 or val > 1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) message = ("\n\nvalue must be -1 or 0 < value <= 1000. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) "Value program received: {}\n").format(val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) raise argparse.ArgumentTypeError(message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return val
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if __name__ == "__main__":
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) main()