1c6dab2a8SThomas Monjalon#! /usr/bin/env python 2c6dab2a8SThomas Monjalon# 3c6dab2a8SThomas Monjalon# BSD LICENSE 4c6dab2a8SThomas Monjalon# 5c6dab2a8SThomas Monjalon# Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 6c6dab2a8SThomas Monjalon# All rights reserved. 7c6dab2a8SThomas Monjalon# 8c6dab2a8SThomas Monjalon# Redistribution and use in source and binary forms, with or without 9c6dab2a8SThomas Monjalon# modification, are permitted provided that the following conditions 10c6dab2a8SThomas Monjalon# are met: 11c6dab2a8SThomas Monjalon# 12c6dab2a8SThomas Monjalon# * Redistributions of source code must retain the above copyright 13c6dab2a8SThomas Monjalon# notice, this list of conditions and the following disclaimer. 14c6dab2a8SThomas Monjalon# * Redistributions in binary form must reproduce the above copyright 15c6dab2a8SThomas Monjalon# notice, this list of conditions and the following disclaimer in 16c6dab2a8SThomas Monjalon# the documentation and/or other materials provided with the 17c6dab2a8SThomas Monjalon# distribution. 18c6dab2a8SThomas Monjalon# * Neither the name of Intel Corporation nor the names of its 19c6dab2a8SThomas Monjalon# contributors may be used to endorse or promote products derived 20c6dab2a8SThomas Monjalon# from this software without specific prior written permission. 21c6dab2a8SThomas Monjalon# 22c6dab2a8SThomas Monjalon# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23c6dab2a8SThomas Monjalon# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24c6dab2a8SThomas Monjalon# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25c6dab2a8SThomas Monjalon# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26c6dab2a8SThomas Monjalon# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27c6dab2a8SThomas Monjalon# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28c6dab2a8SThomas Monjalon# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29c6dab2a8SThomas Monjalon# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30c6dab2a8SThomas Monjalon# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31c6dab2a8SThomas Monjalon# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32c6dab2a8SThomas Monjalon# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33c6dab2a8SThomas Monjalon# 34c6dab2a8SThomas Monjalon 35c6dab2a8SThomas Monjalonimport sys 36c6dab2a8SThomas Monjalonimport os 37c6dab2a8SThomas Monjalonimport getopt 38c6dab2a8SThomas Monjalonimport subprocess 39c6dab2a8SThomas Monjalonfrom os.path import exists, abspath, dirname, basename 40c6dab2a8SThomas Monjalon 418ad08a28SGuduri Prathyusha# The PCI base class for all devices 428ad08a28SGuduri Prathyushanetwork_class = {'Class': '02', 'Vendor': None, 'Device': None, 438ad08a28SGuduri Prathyusha 'SVendor': None, 'SDevice': None} 448ad08a28SGuduri Prathyushaencryption_class = {'Class': '10', 'Vendor': None, 'Device': None, 458ad08a28SGuduri Prathyusha 'SVendor': None, 'SDevice': None} 468ad08a28SGuduri Prathyushaintel_processor_class = {'Class': '0b', 'Vendor': '8086', 'Device': None, 478ad08a28SGuduri Prathyusha 'SVendor': None, 'SDevice': None} 4832a02dbfSGuduri Prathyushacavium_sso = {'Class': '08', 'Vendor': '177d', 'Device': 'a04b,a04d', 4932a02dbfSGuduri Prathyusha 'SVendor': None, 'SDevice': None} 5080a1858dSGuduri Prathyushacavium_fpa = {'Class': '08', 'Vendor': '177d', 'Device': 'a053', 5180a1858dSGuduri Prathyusha 'SVendor': None, 'SDevice': None} 528ad08a28SGuduri Prathyusha 538ad08a28SGuduri Prathyushanetwork_devices = [network_class] 548ad08a28SGuduri Prathyushacrypto_devices = [encryption_class, intel_processor_class] 5532a02dbfSGuduri Prathyushaeventdev_devices = [cavium_sso] 5680a1858dSGuduri Prathyushamempool_devices = [cavium_fpa] 57c6dab2a8SThomas Monjalon 58c6dab2a8SThomas Monjalon# global dict ethernet devices present. Dictionary indexed by PCI address. 59c6dab2a8SThomas Monjalon# Each device within this is itself a dictionary of device properties 60c6dab2a8SThomas Monjalondevices = {} 61c6dab2a8SThomas Monjalon# list of supported DPDK drivers 62c6dab2a8SThomas Monjalondpdk_drivers = ["igb_uio", "vfio-pci", "uio_pci_generic"] 63c6dab2a8SThomas Monjalon 64c6dab2a8SThomas Monjalon# command-line arg flags 65c6dab2a8SThomas Monjalonb_flag = None 66c6dab2a8SThomas Monjalonstatus_flag = False 67c6dab2a8SThomas Monjalonforce_flag = False 68c6dab2a8SThomas Monjalonargs = [] 69c6dab2a8SThomas Monjalon 70c6dab2a8SThomas Monjalon 71c6dab2a8SThomas Monjalondef usage(): 72c6dab2a8SThomas Monjalon '''Print usage information for the program''' 73c6dab2a8SThomas Monjalon argv0 = basename(sys.argv[0]) 74c6dab2a8SThomas Monjalon print(""" 75c6dab2a8SThomas MonjalonUsage: 76c6dab2a8SThomas Monjalon------ 77c6dab2a8SThomas Monjalon 78c6dab2a8SThomas Monjalon %(argv0)s [options] DEVICE1 DEVICE2 .... 79c6dab2a8SThomas Monjalon 80c6dab2a8SThomas Monjalonwhere DEVICE1, DEVICE2 etc, are specified via PCI "domain:bus:slot.func" syntax 81c6dab2a8SThomas Monjalonor "bus:slot.func" syntax. For devices bound to Linux kernel drivers, they may 82c6dab2a8SThomas Monjalonalso be referred to by Linux interface name e.g. eth0, eth1, em0, em1, etc. 83c6dab2a8SThomas Monjalon 84c6dab2a8SThomas MonjalonOptions: 85c6dab2a8SThomas Monjalon --help, --usage: 86c6dab2a8SThomas Monjalon Display usage information and quit 87c6dab2a8SThomas Monjalon 88c6dab2a8SThomas Monjalon -s, --status: 89b153c00bSFerruh Yigit Print the current status of all known network, crypto, event 90b153c00bSFerruh Yigit and mempool devices. 91c6dab2a8SThomas Monjalon For each device, it displays the PCI domain, bus, slot and function, 92c6dab2a8SThomas Monjalon along with a text description of the device. Depending upon whether the 93c6dab2a8SThomas Monjalon device is being used by a kernel driver, the igb_uio driver, or no 94c6dab2a8SThomas Monjalon driver, other relevant information will be displayed: 95c6dab2a8SThomas Monjalon * the Linux interface name e.g. if=eth0 96c6dab2a8SThomas Monjalon * the driver being used e.g. drv=igb_uio 97c6dab2a8SThomas Monjalon * any suitable drivers not currently using that device 98c6dab2a8SThomas Monjalon e.g. unused=igb_uio 99c6dab2a8SThomas Monjalon NOTE: if this flag is passed along with a bind/unbind option, the 100c6dab2a8SThomas Monjalon status display will always occur after the other operations have taken 101c6dab2a8SThomas Monjalon place. 102c6dab2a8SThomas Monjalon 103b153c00bSFerruh Yigit --status-dev: 104b153c00bSFerruh Yigit Print the status of given device group. Supported device groups are: 105b153c00bSFerruh Yigit "net", "crypto", "event" and "mempool" 106b153c00bSFerruh Yigit 107c6dab2a8SThomas Monjalon -b driver, --bind=driver: 108c6dab2a8SThomas Monjalon Select the driver to use or \"none\" to unbind the device 109c6dab2a8SThomas Monjalon 110c6dab2a8SThomas Monjalon -u, --unbind: 111c6dab2a8SThomas Monjalon Unbind a device (Equivalent to \"-b none\") 112c6dab2a8SThomas Monjalon 113c6dab2a8SThomas Monjalon --force: 114c6dab2a8SThomas Monjalon By default, network devices which are used by Linux - as indicated by 115c6dab2a8SThomas Monjalon having routes in the routing table - cannot be modified. Using the 116c6dab2a8SThomas Monjalon --force flag overrides this behavior, allowing active links to be 117c6dab2a8SThomas Monjalon forcibly unbound. 118c6dab2a8SThomas Monjalon WARNING: This can lead to loss of network connection and should be used 119c6dab2a8SThomas Monjalon with caution. 120c6dab2a8SThomas Monjalon 121c6dab2a8SThomas MonjalonExamples: 122c6dab2a8SThomas Monjalon--------- 123c6dab2a8SThomas Monjalon 124c6dab2a8SThomas MonjalonTo display current device status: 125c6dab2a8SThomas Monjalon %(argv0)s --status 126c6dab2a8SThomas Monjalon 127b153c00bSFerruh YigitTo display current network device status: 128b153c00bSFerruh Yigit %(argv0)s --status-dev net 129b153c00bSFerruh Yigit 130c6dab2a8SThomas MonjalonTo bind eth1 from the current driver and move to use igb_uio 131c6dab2a8SThomas Monjalon %(argv0)s --bind=igb_uio eth1 132c6dab2a8SThomas Monjalon 133c6dab2a8SThomas MonjalonTo unbind 0000:01:00.0 from using any driver 134c6dab2a8SThomas Monjalon %(argv0)s -u 0000:01:00.0 135c6dab2a8SThomas Monjalon 136c6dab2a8SThomas MonjalonTo bind 0000:02:00.0 and 0000:02:00.1 to the ixgbe kernel driver 137c6dab2a8SThomas Monjalon %(argv0)s -b ixgbe 02:00.0 02:00.1 138c6dab2a8SThomas Monjalon 139c6dab2a8SThomas Monjalon """ % locals()) # replace items from local variables 140c6dab2a8SThomas Monjalon 141c6dab2a8SThomas Monjalon 142c6dab2a8SThomas Monjalon# This is roughly compatible with check_output function in subprocess module 143c6dab2a8SThomas Monjalon# which is only available in python 2.7. 144c6dab2a8SThomas Monjalondef check_output(args, stderr=None): 145c6dab2a8SThomas Monjalon '''Run a command and capture its output''' 146c6dab2a8SThomas Monjalon return subprocess.Popen(args, stdout=subprocess.PIPE, 147c6dab2a8SThomas Monjalon stderr=stderr).communicate()[0] 148c6dab2a8SThomas Monjalon 149c6dab2a8SThomas Monjalon 150c6dab2a8SThomas Monjalondef find_module(mod): 151c6dab2a8SThomas Monjalon '''find the .ko file for kernel module named mod. 152c6dab2a8SThomas Monjalon Searches the $RTE_SDK/$RTE_TARGET directory, the kernel 153c6dab2a8SThomas Monjalon modules directory and finally under the parent directory of 154c6dab2a8SThomas Monjalon the script ''' 155c6dab2a8SThomas Monjalon # check $RTE_SDK/$RTE_TARGET directory 156c6dab2a8SThomas Monjalon if 'RTE_SDK' in os.environ and 'RTE_TARGET' in os.environ: 157c6dab2a8SThomas Monjalon path = "%s/%s/kmod/%s.ko" % (os.environ['RTE_SDK'], 158c6dab2a8SThomas Monjalon os.environ['RTE_TARGET'], mod) 159c6dab2a8SThomas Monjalon if exists(path): 160c6dab2a8SThomas Monjalon return path 161c6dab2a8SThomas Monjalon 162c6dab2a8SThomas Monjalon # check using depmod 163c6dab2a8SThomas Monjalon try: 164*df86b009SMark Asselstine with open(os.devnull, "w") as fnull: 165*df86b009SMark Asselstine path = check_output(["modinfo", "-n", mod], stderr=fnull).strip() 166*df86b009SMark Asselstine 167*df86b009SMark Asselstine if path and exists(path): 168c6dab2a8SThomas Monjalon return path 169c6dab2a8SThomas Monjalon except: # if modinfo can't find module, it fails, so continue 170c6dab2a8SThomas Monjalon pass 171c6dab2a8SThomas Monjalon 172c6dab2a8SThomas Monjalon # check for a copy based off current path 173c6dab2a8SThomas Monjalon tools_dir = dirname(abspath(sys.argv[0])) 174c6dab2a8SThomas Monjalon if tools_dir.endswith("tools"): 175c6dab2a8SThomas Monjalon base_dir = dirname(tools_dir) 176c6dab2a8SThomas Monjalon find_out = check_output(["find", base_dir, "-name", mod + ".ko"]) 177c6dab2a8SThomas Monjalon if len(find_out) > 0: # something matched 178c6dab2a8SThomas Monjalon path = find_out.splitlines()[0] 179c6dab2a8SThomas Monjalon if exists(path): 180c6dab2a8SThomas Monjalon return path 181c6dab2a8SThomas Monjalon 182c6dab2a8SThomas Monjalon 183c6dab2a8SThomas Monjalondef check_modules(): 184c6dab2a8SThomas Monjalon '''Checks that igb_uio is loaded''' 185c6dab2a8SThomas Monjalon global dpdk_drivers 186c6dab2a8SThomas Monjalon 187c6dab2a8SThomas Monjalon # list of supported modules 188c6dab2a8SThomas Monjalon mods = [{"Name": driver, "Found": False} for driver in dpdk_drivers] 189c6dab2a8SThomas Monjalon 190c6dab2a8SThomas Monjalon # first check if module is loaded 191c6dab2a8SThomas Monjalon try: 192c6dab2a8SThomas Monjalon # Get list of sysfs modules (both built-in and dynamically loaded) 193c6dab2a8SThomas Monjalon sysfs_path = '/sys/module/' 194c6dab2a8SThomas Monjalon 195c6dab2a8SThomas Monjalon # Get the list of directories in sysfs_path 196c6dab2a8SThomas Monjalon sysfs_mods = [os.path.join(sysfs_path, o) for o 197c6dab2a8SThomas Monjalon in os.listdir(sysfs_path) 198c6dab2a8SThomas Monjalon if os.path.isdir(os.path.join(sysfs_path, o))] 199c6dab2a8SThomas Monjalon 200c6dab2a8SThomas Monjalon # Extract the last element of '/sys/module/abc' in the array 201c6dab2a8SThomas Monjalon sysfs_mods = [a.split('/')[-1] for a in sysfs_mods] 202c6dab2a8SThomas Monjalon 203c6dab2a8SThomas Monjalon # special case for vfio_pci (module is named vfio-pci, 204c6dab2a8SThomas Monjalon # but its .ko is named vfio_pci) 205c6dab2a8SThomas Monjalon sysfs_mods = map(lambda a: 206c6dab2a8SThomas Monjalon a if a != 'vfio_pci' else 'vfio-pci', sysfs_mods) 207c6dab2a8SThomas Monjalon 208c6dab2a8SThomas Monjalon for mod in mods: 209c6dab2a8SThomas Monjalon if mod["Name"] in sysfs_mods: 210c6dab2a8SThomas Monjalon mod["Found"] = True 211c6dab2a8SThomas Monjalon except: 212c6dab2a8SThomas Monjalon pass 213c6dab2a8SThomas Monjalon 214c6dab2a8SThomas Monjalon # check if we have at least one loaded module 215c6dab2a8SThomas Monjalon if True not in [mod["Found"] for mod in mods] and b_flag is not None: 216c6dab2a8SThomas Monjalon if b_flag in dpdk_drivers: 217c6dab2a8SThomas Monjalon print("Error - no supported modules(DPDK driver) are loaded") 218c6dab2a8SThomas Monjalon sys.exit(1) 219c6dab2a8SThomas Monjalon else: 220c6dab2a8SThomas Monjalon print("Warning - no supported modules(DPDK driver) are loaded") 221c6dab2a8SThomas Monjalon 222c6dab2a8SThomas Monjalon # change DPDK driver list to only contain drivers that are loaded 223c6dab2a8SThomas Monjalon dpdk_drivers = [mod["Name"] for mod in mods if mod["Found"]] 224c6dab2a8SThomas Monjalon 225c6dab2a8SThomas Monjalon 226c6dab2a8SThomas Monjalondef has_driver(dev_id): 227c6dab2a8SThomas Monjalon '''return true if a device is assigned to a driver. False otherwise''' 228c6dab2a8SThomas Monjalon return "Driver_str" in devices[dev_id] 229c6dab2a8SThomas Monjalon 230c6dab2a8SThomas Monjalon 231c3ce205dSGuduri Prathyushadef get_pci_device_details(dev_id, probe_lspci): 232c6dab2a8SThomas Monjalon '''This function gets additional details for a PCI device''' 233c6dab2a8SThomas Monjalon device = {} 234c6dab2a8SThomas Monjalon 235c3ce205dSGuduri Prathyusha if probe_lspci: 236c6dab2a8SThomas Monjalon extra_info = check_output(["lspci", "-vmmks", dev_id]).splitlines() 237c6dab2a8SThomas Monjalon 238c6dab2a8SThomas Monjalon # parse lspci details 239c6dab2a8SThomas Monjalon for line in extra_info: 240c6dab2a8SThomas Monjalon if len(line) == 0: 241c6dab2a8SThomas Monjalon continue 242c6dab2a8SThomas Monjalon name, value = line.decode().split("\t", 1) 243c6dab2a8SThomas Monjalon name = name.strip(":") + "_str" 244c6dab2a8SThomas Monjalon device[name] = value 245c6dab2a8SThomas Monjalon # check for a unix interface name 246c6dab2a8SThomas Monjalon device["Interface"] = "" 247c6dab2a8SThomas Monjalon for base, dirs, _ in os.walk("/sys/bus/pci/devices/%s/" % dev_id): 248c6dab2a8SThomas Monjalon if "net" in dirs: 249c6dab2a8SThomas Monjalon device["Interface"] = \ 250c6dab2a8SThomas Monjalon ",".join(os.listdir(os.path.join(base, "net"))) 251c6dab2a8SThomas Monjalon break 252c6dab2a8SThomas Monjalon # check if a port is used for ssh connection 253c6dab2a8SThomas Monjalon device["Ssh_if"] = False 254c6dab2a8SThomas Monjalon device["Active"] = "" 255c6dab2a8SThomas Monjalon 256c6dab2a8SThomas Monjalon return device 257c6dab2a8SThomas Monjalon 258ea9f00f7SGuduri Prathyushadef clear_data(): 259ea9f00f7SGuduri Prathyusha '''This function clears any old data''' 260ea9f00f7SGuduri Prathyusha devices = {} 261c6dab2a8SThomas Monjalon 262ea9f00f7SGuduri Prathyushadef get_device_details(devices_type): 263c6dab2a8SThomas Monjalon '''This function populates the "devices" dictionary. The keys used are 264c6dab2a8SThomas Monjalon the pci addresses (domain:bus:slot.func). The values are themselves 265c6dab2a8SThomas Monjalon dictionaries - one for each NIC.''' 266c6dab2a8SThomas Monjalon global devices 267c6dab2a8SThomas Monjalon global dpdk_drivers 268c6dab2a8SThomas Monjalon 269c6dab2a8SThomas Monjalon # first loop through and read details for all devices 270c3ce205dSGuduri Prathyusha # request machine readable format, with numeric IDs and String 271c6dab2a8SThomas Monjalon dev = {} 272c3ce205dSGuduri Prathyusha dev_lines = check_output(["lspci", "-Dvmmnnk"]).splitlines() 273c6dab2a8SThomas Monjalon for dev_line in dev_lines: 274c6dab2a8SThomas Monjalon if len(dev_line) == 0: 2758ad08a28SGuduri Prathyusha if device_type_match(dev, devices_type): 2768ad08a28SGuduri Prathyusha # Replace "Driver" with "Driver_str" to have consistency of 2778ad08a28SGuduri Prathyusha # of dictionary key names 278c3ce205dSGuduri Prathyusha if "Driver" in dev.keys(): 279c3ce205dSGuduri Prathyusha dev["Driver_str"] = dev.pop("Driver") 280c6dab2a8SThomas Monjalon # use dict to make copy of dev 281c6dab2a8SThomas Monjalon devices[dev["Slot"]] = dict(dev) 282c3ce205dSGuduri Prathyusha # Clear previous device's data 283c3ce205dSGuduri Prathyusha dev = {} 284c6dab2a8SThomas Monjalon else: 285c6dab2a8SThomas Monjalon name, value = dev_line.decode().split("\t", 1) 286c3ce205dSGuduri Prathyusha value_list = value.rsplit(' ', 1) 287c3ce205dSGuduri Prathyusha if len(value_list) > 1: 288c3ce205dSGuduri Prathyusha # String stored in <name>_str 289c3ce205dSGuduri Prathyusha dev[name.rstrip(":") + '_str'] = value_list[0] 290c3ce205dSGuduri Prathyusha # Numeric IDs 291c3ce205dSGuduri Prathyusha dev[name.rstrip(":")] = value_list[len(value_list) - 1] \ 292c3ce205dSGuduri Prathyusha .rstrip("]").lstrip("[") 293c6dab2a8SThomas Monjalon 2948ad08a28SGuduri Prathyusha if devices_type == network_devices: 295c6dab2a8SThomas Monjalon # check what is the interface if any for an ssh connection if 296c6dab2a8SThomas Monjalon # any to this host, so we can mark it later. 297c6dab2a8SThomas Monjalon ssh_if = [] 298c6dab2a8SThomas Monjalon route = check_output(["ip", "-o", "route"]) 299c6dab2a8SThomas Monjalon # filter out all lines for 169.254 routes 300c6dab2a8SThomas Monjalon route = "\n".join(filter(lambda ln: not ln.startswith("169.254"), 301c6dab2a8SThomas Monjalon route.decode().splitlines())) 302c6dab2a8SThomas Monjalon rt_info = route.split() 303c6dab2a8SThomas Monjalon for i in range(len(rt_info) - 1): 304c6dab2a8SThomas Monjalon if rt_info[i] == "dev": 305c6dab2a8SThomas Monjalon ssh_if.append(rt_info[i+1]) 306c6dab2a8SThomas Monjalon 307c6dab2a8SThomas Monjalon # based on the basic info, get extended text details 308c6dab2a8SThomas Monjalon for d in devices.keys(): 3098ad08a28SGuduri Prathyusha if not device_type_match(devices[d], devices_type): 310617d9052SYoni Gilad continue 311617d9052SYoni Gilad 312c6dab2a8SThomas Monjalon # get additional info and add it to existing data 313c6dab2a8SThomas Monjalon devices[d] = devices[d].copy() 314c3ce205dSGuduri Prathyusha # No need to probe lspci 315c3ce205dSGuduri Prathyusha devices[d].update(get_pci_device_details(d, False).items()) 316c6dab2a8SThomas Monjalon 3178ad08a28SGuduri Prathyusha if devices_type == network_devices: 318ea9f00f7SGuduri Prathyusha for _if in ssh_if: 319ea9f00f7SGuduri Prathyusha if _if in devices[d]["Interface"].split(","): 320ea9f00f7SGuduri Prathyusha devices[d]["Ssh_if"] = True 321ea9f00f7SGuduri Prathyusha devices[d]["Active"] = "*Active*" 322ea9f00f7SGuduri Prathyusha break 323ea9f00f7SGuduri Prathyusha 324c6dab2a8SThomas Monjalon # add igb_uio to list of supporting modules if needed 325c6dab2a8SThomas Monjalon if "Module_str" in devices[d]: 326c6dab2a8SThomas Monjalon for driver in dpdk_drivers: 327c6dab2a8SThomas Monjalon if driver not in devices[d]["Module_str"]: 328c6dab2a8SThomas Monjalon devices[d]["Module_str"] = \ 329c6dab2a8SThomas Monjalon devices[d]["Module_str"] + ",%s" % driver 330c6dab2a8SThomas Monjalon else: 331c6dab2a8SThomas Monjalon devices[d]["Module_str"] = ",".join(dpdk_drivers) 332c6dab2a8SThomas Monjalon 333c6dab2a8SThomas Monjalon # make sure the driver and module strings do not have any duplicates 334c6dab2a8SThomas Monjalon if has_driver(d): 335c6dab2a8SThomas Monjalon modules = devices[d]["Module_str"].split(",") 336c6dab2a8SThomas Monjalon if devices[d]["Driver_str"] in modules: 337c6dab2a8SThomas Monjalon modules.remove(devices[d]["Driver_str"]) 338c6dab2a8SThomas Monjalon devices[d]["Module_str"] = ",".join(modules) 339c6dab2a8SThomas Monjalon 340c6dab2a8SThomas Monjalon 3418ad08a28SGuduri Prathyushadef device_type_match(dev, devices_type): 3428ad08a28SGuduri Prathyusha for i in range(len(devices_type)): 3438ad08a28SGuduri Prathyusha param_count = len( 3448ad08a28SGuduri Prathyusha [x for x in devices_type[i].values() if x is not None]) 3458ad08a28SGuduri Prathyusha match_count = 0 3468ad08a28SGuduri Prathyusha if dev["Class"][0:2] == devices_type[i]["Class"]: 3478ad08a28SGuduri Prathyusha match_count = match_count + 1 3488ad08a28SGuduri Prathyusha for key in devices_type[i].keys(): 3498ad08a28SGuduri Prathyusha if key != 'Class' and devices_type[i][key]: 3508ad08a28SGuduri Prathyusha value_list = devices_type[i][key].split(',') 3518ad08a28SGuduri Prathyusha for value in value_list: 3528ad08a28SGuduri Prathyusha if value.strip(' ') == dev[key]: 3538ad08a28SGuduri Prathyusha match_count = match_count + 1 3548ad08a28SGuduri Prathyusha # count must be the number of non None parameters to match 3558ad08a28SGuduri Prathyusha if match_count == param_count: 3568ad08a28SGuduri Prathyusha return True 3578ad08a28SGuduri Prathyusha else: 3588ad08a28SGuduri Prathyusha return False 3598ad08a28SGuduri Prathyusha 360c6dab2a8SThomas Monjalondef dev_id_from_dev_name(dev_name): 361c6dab2a8SThomas Monjalon '''Take a device "name" - a string passed in by user to identify a NIC 362c6dab2a8SThomas Monjalon device, and determine the device id - i.e. the domain:bus:slot.func - for 363c6dab2a8SThomas Monjalon it, which can then be used to index into the devices array''' 364c6dab2a8SThomas Monjalon 365c6dab2a8SThomas Monjalon # check if it's already a suitable index 366c6dab2a8SThomas Monjalon if dev_name in devices: 367c6dab2a8SThomas Monjalon return dev_name 368c6dab2a8SThomas Monjalon # check if it's an index just missing the domain part 369c6dab2a8SThomas Monjalon elif "0000:" + dev_name in devices: 370c6dab2a8SThomas Monjalon return "0000:" + dev_name 371c6dab2a8SThomas Monjalon else: 372c6dab2a8SThomas Monjalon # check if it's an interface name, e.g. eth1 373c6dab2a8SThomas Monjalon for d in devices.keys(): 374c6dab2a8SThomas Monjalon if dev_name in devices[d]["Interface"].split(","): 375c6dab2a8SThomas Monjalon return devices[d]["Slot"] 376c6dab2a8SThomas Monjalon # if nothing else matches - error 377c6dab2a8SThomas Monjalon print("Unknown device: %s. " 378c6dab2a8SThomas Monjalon "Please specify device in \"bus:slot.func\" format" % dev_name) 379c6dab2a8SThomas Monjalon sys.exit(1) 380c6dab2a8SThomas Monjalon 381c6dab2a8SThomas Monjalon 382c6dab2a8SThomas Monjalondef unbind_one(dev_id, force): 383c6dab2a8SThomas Monjalon '''Unbind the device identified by "dev_id" from its current driver''' 384c6dab2a8SThomas Monjalon dev = devices[dev_id] 385c6dab2a8SThomas Monjalon if not has_driver(dev_id): 386c6dab2a8SThomas Monjalon print("%s %s %s is not currently managed by any driver\n" % 387c6dab2a8SThomas Monjalon (dev["Slot"], dev["Device_str"], dev["Interface"])) 388c6dab2a8SThomas Monjalon return 389c6dab2a8SThomas Monjalon 390c6dab2a8SThomas Monjalon # prevent us disconnecting ourselves 391c6dab2a8SThomas Monjalon if dev["Ssh_if"] and not force: 392c6dab2a8SThomas Monjalon print("Routing table indicates that interface %s is active. " 393c6dab2a8SThomas Monjalon "Skipping unbind" % (dev_id)) 394c6dab2a8SThomas Monjalon return 395c6dab2a8SThomas Monjalon 396c6dab2a8SThomas Monjalon # write to /sys to unbind 397c6dab2a8SThomas Monjalon filename = "/sys/bus/pci/drivers/%s/unbind" % dev["Driver_str"] 398c6dab2a8SThomas Monjalon try: 399c6dab2a8SThomas Monjalon f = open(filename, "a") 400c6dab2a8SThomas Monjalon except: 401c6dab2a8SThomas Monjalon print("Error: unbind failed for %s - Cannot open %s" 402c6dab2a8SThomas Monjalon % (dev_id, filename)) 403c6dab2a8SThomas Monjalon sys.exit(1) 404c6dab2a8SThomas Monjalon f.write(dev_id) 405c6dab2a8SThomas Monjalon f.close() 406c6dab2a8SThomas Monjalon 407c6dab2a8SThomas Monjalon 408c6dab2a8SThomas Monjalondef bind_one(dev_id, driver, force): 409c6dab2a8SThomas Monjalon '''Bind the device given by "dev_id" to the driver "driver". If the device 410c6dab2a8SThomas Monjalon is already bound to a different driver, it will be unbound first''' 411c6dab2a8SThomas Monjalon dev = devices[dev_id] 412c6dab2a8SThomas Monjalon saved_driver = None # used to rollback any unbind in case of failure 413c6dab2a8SThomas Monjalon 414c6dab2a8SThomas Monjalon # prevent disconnection of our ssh session 415c6dab2a8SThomas Monjalon if dev["Ssh_if"] and not force: 416c6dab2a8SThomas Monjalon print("Routing table indicates that interface %s is active. " 417c6dab2a8SThomas Monjalon "Not modifying" % (dev_id)) 418c6dab2a8SThomas Monjalon return 419c6dab2a8SThomas Monjalon 420c6dab2a8SThomas Monjalon # unbind any existing drivers we don't want 421c6dab2a8SThomas Monjalon if has_driver(dev_id): 422c6dab2a8SThomas Monjalon if dev["Driver_str"] == driver: 423c6dab2a8SThomas Monjalon print("%s already bound to driver %s, skipping\n" 424c6dab2a8SThomas Monjalon % (dev_id, driver)) 425c6dab2a8SThomas Monjalon return 426c6dab2a8SThomas Monjalon else: 427c6dab2a8SThomas Monjalon saved_driver = dev["Driver_str"] 428c6dab2a8SThomas Monjalon unbind_one(dev_id, force) 429c6dab2a8SThomas Monjalon dev["Driver_str"] = "" # clear driver string 430c6dab2a8SThomas Monjalon 4312fc35029SGuduri Prathyusha # For kernels >= 3.15 driver_override can be used to specify the driver 4322fc35029SGuduri Prathyusha # for a device rather than relying on the driver to provide a positive 4332fc35029SGuduri Prathyusha # match of the device. The existing process of looking up 4342fc35029SGuduri Prathyusha # the vendor and device ID, adding them to the driver new_id, 4352fc35029SGuduri Prathyusha # will erroneously bind other devices too which has the additional burden 4362fc35029SGuduri Prathyusha # of unbinding those devices 437c6dab2a8SThomas Monjalon if driver in dpdk_drivers: 4382fc35029SGuduri Prathyusha filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id 4392fc35029SGuduri Prathyusha if os.path.exists(filename): 4402fc35029SGuduri Prathyusha try: 4412fc35029SGuduri Prathyusha f = open(filename, "w") 4422fc35029SGuduri Prathyusha except: 4432fc35029SGuduri Prathyusha print("Error: bind failed for %s - Cannot open %s" 4442fc35029SGuduri Prathyusha % (dev_id, filename)) 4452fc35029SGuduri Prathyusha return 4462fc35029SGuduri Prathyusha try: 4472fc35029SGuduri Prathyusha f.write("%s" % driver) 4482fc35029SGuduri Prathyusha f.close() 4492fc35029SGuduri Prathyusha except: 4502fc35029SGuduri Prathyusha print("Error: bind failed for %s - Cannot write driver %s to " 4512fc35029SGuduri Prathyusha "PCI ID " % (dev_id, driver)) 4522fc35029SGuduri Prathyusha return 4532fc35029SGuduri Prathyusha # For kernels < 3.15 use new_id to add PCI id's to the driver 4542fc35029SGuduri Prathyusha else: 455c6dab2a8SThomas Monjalon filename = "/sys/bus/pci/drivers/%s/new_id" % driver 456c6dab2a8SThomas Monjalon try: 457c6dab2a8SThomas Monjalon f = open(filename, "w") 458c6dab2a8SThomas Monjalon except: 459c6dab2a8SThomas Monjalon print("Error: bind failed for %s - Cannot open %s" 460c6dab2a8SThomas Monjalon % (dev_id, filename)) 461c6dab2a8SThomas Monjalon return 462c6dab2a8SThomas Monjalon try: 4638ad08a28SGuduri Prathyusha # Convert Device and Vendor Id to int to write to new_id 4648ad08a28SGuduri Prathyusha f.write("%04x %04x" % (int(dev["Vendor"],16), 4658ad08a28SGuduri Prathyusha int(dev["Device"], 16))) 466c6dab2a8SThomas Monjalon f.close() 467c6dab2a8SThomas Monjalon except: 468c6dab2a8SThomas Monjalon print("Error: bind failed for %s - Cannot write new PCI ID to " 469c6dab2a8SThomas Monjalon "driver %s" % (dev_id, driver)) 470c6dab2a8SThomas Monjalon return 471c6dab2a8SThomas Monjalon 472c6dab2a8SThomas Monjalon # do the bind by writing to /sys 473c6dab2a8SThomas Monjalon filename = "/sys/bus/pci/drivers/%s/bind" % driver 474c6dab2a8SThomas Monjalon try: 475c6dab2a8SThomas Monjalon f = open(filename, "a") 476c6dab2a8SThomas Monjalon except: 477c6dab2a8SThomas Monjalon print("Error: bind failed for %s - Cannot open %s" 478c6dab2a8SThomas Monjalon % (dev_id, filename)) 479c6dab2a8SThomas Monjalon if saved_driver is not None: # restore any previous driver 480c6dab2a8SThomas Monjalon bind_one(dev_id, saved_driver, force) 481c6dab2a8SThomas Monjalon return 482c6dab2a8SThomas Monjalon try: 483c6dab2a8SThomas Monjalon f.write(dev_id) 484c6dab2a8SThomas Monjalon f.close() 485c6dab2a8SThomas Monjalon except: 486c6dab2a8SThomas Monjalon # for some reason, closing dev_id after adding a new PCI ID to new_id 487c6dab2a8SThomas Monjalon # results in IOError. however, if the device was successfully bound, 488c6dab2a8SThomas Monjalon # we don't care for any errors and can safely ignore IOError 489c3ce205dSGuduri Prathyusha tmp = get_pci_device_details(dev_id, True) 490c6dab2a8SThomas Monjalon if "Driver_str" in tmp and tmp["Driver_str"] == driver: 491c6dab2a8SThomas Monjalon return 492c6dab2a8SThomas Monjalon print("Error: bind failed for %s - Cannot bind to driver %s" 493c6dab2a8SThomas Monjalon % (dev_id, driver)) 494c6dab2a8SThomas Monjalon if saved_driver is not None: # restore any previous driver 495c6dab2a8SThomas Monjalon bind_one(dev_id, saved_driver, force) 496c6dab2a8SThomas Monjalon return 497c6dab2a8SThomas Monjalon 498720b7a05SGuduri Prathyusha # For kernels > 3.15 driver_override is used to bind a device to a driver. 499720b7a05SGuduri Prathyusha # Before unbinding it, overwrite driver_override with empty string so that 500720b7a05SGuduri Prathyusha # the device can be bound to any other driver 501720b7a05SGuduri Prathyusha filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id 502720b7a05SGuduri Prathyusha if os.path.exists(filename): 503720b7a05SGuduri Prathyusha try: 504720b7a05SGuduri Prathyusha f = open(filename, "w") 505720b7a05SGuduri Prathyusha except: 506720b7a05SGuduri Prathyusha print("Error: unbind failed for %s - Cannot open %s" 507720b7a05SGuduri Prathyusha % (dev_id, filename)) 508720b7a05SGuduri Prathyusha sys.exit(1) 509720b7a05SGuduri Prathyusha try: 510720b7a05SGuduri Prathyusha f.write("\00") 511720b7a05SGuduri Prathyusha f.close() 512720b7a05SGuduri Prathyusha except: 513720b7a05SGuduri Prathyusha print("Error: unbind failed for %s - Cannot open %s" 514720b7a05SGuduri Prathyusha % (dev_id, filename)) 515720b7a05SGuduri Prathyusha sys.exit(1) 516720b7a05SGuduri Prathyusha 517c6dab2a8SThomas Monjalon 518c6dab2a8SThomas Monjalondef unbind_all(dev_list, force=False): 519c6dab2a8SThomas Monjalon """Unbind method, takes a list of device locations""" 520c6dab2a8SThomas Monjalon dev_list = map(dev_id_from_dev_name, dev_list) 521c6dab2a8SThomas Monjalon for d in dev_list: 522c6dab2a8SThomas Monjalon unbind_one(d, force) 523c6dab2a8SThomas Monjalon 524c6dab2a8SThomas Monjalon 525c6dab2a8SThomas Monjalondef bind_all(dev_list, driver, force=False): 526c6dab2a8SThomas Monjalon """Bind method, takes a list of device locations""" 527c6dab2a8SThomas Monjalon global devices 528c6dab2a8SThomas Monjalon 529c6dab2a8SThomas Monjalon dev_list = map(dev_id_from_dev_name, dev_list) 530c6dab2a8SThomas Monjalon 531c6dab2a8SThomas Monjalon for d in dev_list: 532c6dab2a8SThomas Monjalon bind_one(d, driver, force) 533c6dab2a8SThomas Monjalon 5342fc35029SGuduri Prathyusha # For kenels < 3.15 when binding devices to a generic driver 5352fc35029SGuduri Prathyusha # (i.e. one that doesn't have a PCI ID table) using new_id, some devices 5362fc35029SGuduri Prathyusha # that are not bound to any other driver could be bound even if no one has 5372fc35029SGuduri Prathyusha # asked them to. hence, we check the list of drivers again, and see if 5382fc35029SGuduri Prathyusha # some of the previously-unbound devices were erroneously bound. 5392fc35029SGuduri Prathyusha if not os.path.exists("/sys/bus/pci/devices/%s/driver_override" % d): 540c6dab2a8SThomas Monjalon for d in devices.keys(): 541c6dab2a8SThomas Monjalon # skip devices that were already bound or that we know should be bound 542c6dab2a8SThomas Monjalon if "Driver_str" in devices[d] or d in dev_list: 543c6dab2a8SThomas Monjalon continue 544c6dab2a8SThomas Monjalon 545c6dab2a8SThomas Monjalon # update information about this device 546c6dab2a8SThomas Monjalon devices[d] = dict(devices[d].items() + 547c3ce205dSGuduri Prathyusha get_pci_device_details(d, True).items()) 548c6dab2a8SThomas Monjalon 549c6dab2a8SThomas Monjalon # check if updated information indicates that the device was bound 550c6dab2a8SThomas Monjalon if "Driver_str" in devices[d]: 551c6dab2a8SThomas Monjalon unbind_one(d, force) 552c6dab2a8SThomas Monjalon 553c6dab2a8SThomas Monjalon 554c6dab2a8SThomas Monjalondef display_devices(title, dev_list, extra_params=None): 555c6dab2a8SThomas Monjalon '''Displays to the user the details of a list of devices given in 556c6dab2a8SThomas Monjalon "dev_list". The "extra_params" parameter, if given, should contain a string 557c6dab2a8SThomas Monjalon with %()s fields in it for replacement by the named fields in each 558c6dab2a8SThomas Monjalon device's dictionary.''' 559c6dab2a8SThomas Monjalon strings = [] # this holds the strings to print. We sort before printing 560c6dab2a8SThomas Monjalon print("\n%s" % title) 561c6dab2a8SThomas Monjalon print("="*len(title)) 562c6dab2a8SThomas Monjalon if len(dev_list) == 0: 563c6dab2a8SThomas Monjalon strings.append("<none>") 564c6dab2a8SThomas Monjalon else: 565c6dab2a8SThomas Monjalon for dev in dev_list: 566c6dab2a8SThomas Monjalon if extra_params is not None: 567c3ce205dSGuduri Prathyusha strings.append("%s '%s %s' %s" % (dev["Slot"], 568c6dab2a8SThomas Monjalon dev["Device_str"], 569c3ce205dSGuduri Prathyusha dev["Device"], 570c6dab2a8SThomas Monjalon extra_params % dev)) 571c6dab2a8SThomas Monjalon else: 572c6dab2a8SThomas Monjalon strings.append("%s '%s'" % (dev["Slot"], dev["Device_str"])) 573c6dab2a8SThomas Monjalon # sort before printing, so that the entries appear in PCI order 574c6dab2a8SThomas Monjalon strings.sort() 575c6dab2a8SThomas Monjalon print("\n".join(strings)) # print one per line 576c6dab2a8SThomas Monjalon 577c7dd412bSGuduri Prathyushadef show_device_status(devices_type, device_name): 578c6dab2a8SThomas Monjalon global dpdk_drivers 579c6dab2a8SThomas Monjalon kernel_drv = [] 580c6dab2a8SThomas Monjalon dpdk_drv = [] 581c6dab2a8SThomas Monjalon no_drv = [] 582c6dab2a8SThomas Monjalon 583c6dab2a8SThomas Monjalon # split our list of network devices into the three categories above 584c6dab2a8SThomas Monjalon for d in devices.keys(): 5858ad08a28SGuduri Prathyusha if device_type_match(devices[d], devices_type): 586c6dab2a8SThomas Monjalon if not has_driver(d): 587c6dab2a8SThomas Monjalon no_drv.append(devices[d]) 588c6dab2a8SThomas Monjalon continue 589c6dab2a8SThomas Monjalon if devices[d]["Driver_str"] in dpdk_drivers: 590c6dab2a8SThomas Monjalon dpdk_drv.append(devices[d]) 591c6dab2a8SThomas Monjalon else: 592c6dab2a8SThomas Monjalon kernel_drv.append(devices[d]) 593c6dab2a8SThomas Monjalon 594c6dab2a8SThomas Monjalon # print each category separately, so we can clearly see what's used by DPDK 5958ad08a28SGuduri Prathyusha display_devices("%s devices using DPDK-compatible driver" % device_name, 5968ad08a28SGuduri Prathyusha dpdk_drv, "drv=%(Driver_str)s unused=%(Module_str)s") 597c7dd412bSGuduri Prathyusha display_devices("%s devices using kernel driver" % device_name, kernel_drv, 598c6dab2a8SThomas Monjalon "if=%(Interface)s drv=%(Driver_str)s " 599c6dab2a8SThomas Monjalon "unused=%(Module_str)s %(Active)s") 6008ad08a28SGuduri Prathyusha display_devices("Other %s devices" % device_name, no_drv, 6018ad08a28SGuduri Prathyusha "unused=%(Module_str)s") 602c6dab2a8SThomas Monjalon 603c7dd412bSGuduri Prathyushadef show_status(): 604c7dd412bSGuduri Prathyusha '''Function called when the script is passed the "--status" option. 605c7dd412bSGuduri Prathyusha Displays to the user what devices are bound to the igb_uio driver, the 606c7dd412bSGuduri Prathyusha kernel driver or to no driver''' 607c6dab2a8SThomas Monjalon 608b153c00bSFerruh Yigit if status_dev == "net" or status_dev == "all": 609c7dd412bSGuduri Prathyusha show_device_status(network_devices, "Network") 610b153c00bSFerruh Yigit 611b153c00bSFerruh Yigit if status_dev == "crypto" or status_dev == "all": 612c7dd412bSGuduri Prathyusha show_device_status(crypto_devices, "Crypto") 613b153c00bSFerruh Yigit 614b153c00bSFerruh Yigit if status_dev == "event" or status_dev == "all": 61532a02dbfSGuduri Prathyusha show_device_status(eventdev_devices, "Eventdev") 616b153c00bSFerruh Yigit 617b153c00bSFerruh Yigit if status_dev == "mempool" or status_dev == "all": 61880a1858dSGuduri Prathyusha show_device_status(mempool_devices, "Mempool") 619c6dab2a8SThomas Monjalon 620c6dab2a8SThomas Monjalondef parse_args(): 621c6dab2a8SThomas Monjalon '''Parses the command-line arguments given by the user and takes the 622c6dab2a8SThomas Monjalon appropriate action for each''' 623c6dab2a8SThomas Monjalon global b_flag 624c6dab2a8SThomas Monjalon global status_flag 625b153c00bSFerruh Yigit global status_dev 626c6dab2a8SThomas Monjalon global force_flag 627c6dab2a8SThomas Monjalon global args 628c6dab2a8SThomas Monjalon if len(sys.argv) <= 1: 629c6dab2a8SThomas Monjalon usage() 630c6dab2a8SThomas Monjalon sys.exit(0) 631c6dab2a8SThomas Monjalon 632c6dab2a8SThomas Monjalon try: 633c6dab2a8SThomas Monjalon opts, args = getopt.getopt(sys.argv[1:], "b:us", 634b153c00bSFerruh Yigit ["help", "usage", "status", "status-dev=", 635b153c00bSFerruh Yigit "force", "bind=", "unbind", ]) 636c6dab2a8SThomas Monjalon except getopt.GetoptError as error: 637c6dab2a8SThomas Monjalon print(str(error)) 638c6dab2a8SThomas Monjalon print("Run '%s --usage' for further information" % sys.argv[0]) 639c6dab2a8SThomas Monjalon sys.exit(1) 640c6dab2a8SThomas Monjalon 641c6dab2a8SThomas Monjalon for opt, arg in opts: 642c6dab2a8SThomas Monjalon if opt == "--help" or opt == "--usage": 643c6dab2a8SThomas Monjalon usage() 644c6dab2a8SThomas Monjalon sys.exit(0) 645b153c00bSFerruh Yigit if opt == "--status-dev": 646b153c00bSFerruh Yigit status_flag = True 647b153c00bSFerruh Yigit status_dev = arg 648c6dab2a8SThomas Monjalon if opt == "--status" or opt == "-s": 649c6dab2a8SThomas Monjalon status_flag = True 650b153c00bSFerruh Yigit status_dev = "all" 651c6dab2a8SThomas Monjalon if opt == "--force": 652c6dab2a8SThomas Monjalon force_flag = True 653c6dab2a8SThomas Monjalon if opt == "-b" or opt == "-u" or opt == "--bind" or opt == "--unbind": 654c6dab2a8SThomas Monjalon if b_flag is not None: 655c6dab2a8SThomas Monjalon print("Error - Only one bind or unbind may be specified\n") 656c6dab2a8SThomas Monjalon sys.exit(1) 657c6dab2a8SThomas Monjalon if opt == "-u" or opt == "--unbind": 658c6dab2a8SThomas Monjalon b_flag = "none" 659c6dab2a8SThomas Monjalon else: 660c6dab2a8SThomas Monjalon b_flag = arg 661c6dab2a8SThomas Monjalon 662c6dab2a8SThomas Monjalon 663c6dab2a8SThomas Monjalondef do_arg_actions(): 664c6dab2a8SThomas Monjalon '''do the actual action requested by the user''' 665c6dab2a8SThomas Monjalon global b_flag 666c6dab2a8SThomas Monjalon global status_flag 667c6dab2a8SThomas Monjalon global force_flag 668c6dab2a8SThomas Monjalon global args 669c6dab2a8SThomas Monjalon 670c6dab2a8SThomas Monjalon if b_flag is None and not status_flag: 671c6dab2a8SThomas Monjalon print("Error: No action specified for devices." 672c6dab2a8SThomas Monjalon "Please give a -b or -u option") 673c6dab2a8SThomas Monjalon print("Run '%s --usage' for further information" % sys.argv[0]) 674c6dab2a8SThomas Monjalon sys.exit(1) 675c6dab2a8SThomas Monjalon 676c6dab2a8SThomas Monjalon if b_flag is not None and len(args) == 0: 677c6dab2a8SThomas Monjalon print("Error: No devices specified.") 678c6dab2a8SThomas Monjalon print("Run '%s --usage' for further information" % sys.argv[0]) 679c6dab2a8SThomas Monjalon sys.exit(1) 680c6dab2a8SThomas Monjalon 681c6dab2a8SThomas Monjalon if b_flag == "none" or b_flag == "None": 682c6dab2a8SThomas Monjalon unbind_all(args, force_flag) 683c6dab2a8SThomas Monjalon elif b_flag is not None: 684c6dab2a8SThomas Monjalon bind_all(args, b_flag, force_flag) 685c6dab2a8SThomas Monjalon if status_flag: 686c6dab2a8SThomas Monjalon if b_flag is not None: 687ea9f00f7SGuduri Prathyusha clear_data() 6888ad08a28SGuduri Prathyusha # refresh if we have changed anything 6898ad08a28SGuduri Prathyusha get_device_details(network_devices) 6908ad08a28SGuduri Prathyusha get_device_details(crypto_devices) 69132a02dbfSGuduri Prathyusha get_device_details(eventdev_devices) 69280a1858dSGuduri Prathyusha get_device_details(mempool_devices) 693c6dab2a8SThomas Monjalon show_status() 694c6dab2a8SThomas Monjalon 695c6dab2a8SThomas Monjalon 696c6dab2a8SThomas Monjalondef main(): 697c6dab2a8SThomas Monjalon '''program main function''' 698c6dab2a8SThomas Monjalon parse_args() 699c6dab2a8SThomas Monjalon check_modules() 700ea9f00f7SGuduri Prathyusha clear_data() 7018ad08a28SGuduri Prathyusha get_device_details(network_devices) 7028ad08a28SGuduri Prathyusha get_device_details(crypto_devices) 70332a02dbfSGuduri Prathyusha get_device_details(eventdev_devices) 70480a1858dSGuduri Prathyusha get_device_details(mempool_devices) 705c6dab2a8SThomas Monjalon do_arg_actions() 706c6dab2a8SThomas Monjalon 707c6dab2a8SThomas Monjalonif __name__ == "__main__": 708c6dab2a8SThomas Monjalon main() 709