# global dict ethernet devices present. Dictionary indexed by PCI address.
# Each device within this is itself a dictionary of device properties
devices = {}
+# list of supported DPDK drivers
+dpdk_drivers = [ "igb_uio", "vfio-pci", "uio_pci_generic" ]
+
+# command-line arg flags
+b_flag = None
+status_flag = False
+force_flag = False
+args = []
def usage():
'''Print usage information for the program'''
def check_modules():
'''Checks that igb_uio is loaded'''
+ global dpdk_drivers
fd = file("/proc/modules")
loaded_mods = fd.readlines()
fd.close()
- mod = "igb_uio"
+
+ # list of supported modules
+ mods = [{"Name" : driver, "Found" : False} for driver in dpdk_drivers]
# first check if module is loaded
- found = False
for line in loaded_mods:
- if line.startswith(mod):
- found = True
- break
- if not found:
- print "Error - module %s not loaded" %mod
+ for mod in mods:
+ if line.startswith(mod["Name"]):
+ mod["Found"] = True
+ # special case for vfio_pci (module is named vfio-pci,
+ # but its .ko is named vfio_pci)
+ elif line.replace("_", "-").startswith(mod["Name"]):
+ mod["Found"] = True
+
+ # check if we have at least one loaded module
+ if True not in [mod["Found"] for mod in mods] and b_flag is not None:
+ print "Error - no supported modules are loaded"
sys.exit(1)
+ # change DPDK driver list to only contain drivers that are loaded
+ dpdk_drivers = [mod["Name"] for mod in mods if mod["Found"]]
+
def has_driver(dev_id):
'''return true if a device is assigned to a driver. False otherwise'''
return "Driver_str" in devices[dev_id]
the pci addresses (domain:bus:slot.func). The values are themselves
dictionaries - one for each NIC.'''
global devices
+ global dpdk_drivers
# clear any old data
devices = {}
# add igb_uio to list of supporting modules if needed
if "Module_str" in devices[d]:
- if "igb_uio" not in devices[d]["Module_str"]:
- devices[d]["Module_str"] = devices[d]["Module_str"] + ",igb_uio"
+ for driver in dpdk_drivers:
+ if driver not in devices[d]["Module_str"]:
+ devices[d]["Module_str"] = devices[d]["Module_str"] + ",%s" % driver
else:
- devices[d]["Module_str"] = "igb_uio"
+ devices[d]["Module_str"] = ",".join(dpdk_drivers)
# make sure the driver and module strings do not have any duplicates
if has_driver(d):
dev["Driver_str"] = "" # clear driver string
# if we are binding to one of DPDK drivers, add PCI id's to that driver
- if driver == "igb_uio":
+ if driver in dpdk_drivers:
filename = "/sys/bus/pci/drivers/%s/new_id" % driver
try:
f = open(filename, "w")
def bind_all(dev_list, driver, force=False):
"""Unbind method, takes a list of device locations"""
+ global devices
+
dev_list = map(dev_id_from_dev_name, dev_list)
+
for d in dev_list:
bind_one(d, driver, force)
+ # when binding devices to a generic driver (i.e. one that doesn't have a
+ # PCI ID table), some devices that are not bound to any other driver could
+ # be bound even if no one has asked them to. hence, we check the list of
+ # drivers again, and see if some of the previously-unbound devices were
+ # erroneously bound.
+ for d in devices.keys():
+ # skip devices that were already bound or that we know should be bound
+ if "Driver_str" in devices[d] or d in dev_list:
+ continue
+
+ # update information about this device
+ devices[d] = dict(devices[d].items() +
+ get_pci_device_details(d).items())
+
+ # check if updated information indicates that the device was bound
+ if "Driver_str" in devices[d]:
+ unbind_one(d, force)
+
def display_devices(title, dev_list, extra_params = None):
'''Displays to the user the details of a list of devices given in "dev_list"
The "extra_params" parameter, if given, should contain a string with
'''Function called when the script is passed the "--status" option. Displays
to the user what devices are bound to the igb_uio driver, the kernel driver
or to no driver'''
+ global dpdk_drivers
kernel_drv = []
- uio_drv = []
+ dpdk_drv = []
no_drv = []
+
# split our list of devices into the three categories above
for d in devices.keys():
if not has_driver(d):
no_drv.append(devices[d])
continue
- if devices[d]["Driver_str"] == "igb_uio":
- uio_drv.append(devices[d])
+ if devices[d]["Driver_str"] in dpdk_drivers:
+ dpdk_drv.append(devices[d])
else:
kernel_drv.append(devices[d])
# print each category separately, so we can clearly see what's used by DPDK
- display_devices("Network devices using IGB_UIO driver", uio_drv, \
+ display_devices("Network devices using DPDK-compatible driver", dpdk_drv, \
"drv=%(Driver_str)s unused=%(Module_str)s")
display_devices("Network devices using kernel driver", kernel_drv,
"if=%(Interface)s drv=%(Driver_str)s unused=%(Module_str)s %(Active)s")
def parse_args():
'''Parses the command-line arguments given by the user and takes the
appropriate action for each'''
- b_flag = None
- status_flag = False
- force_flag = False
+ global b_flag
+ global status_flag
+ global force_flag
+ global args
if len(sys.argv) <= 1:
usage()
sys.exit(0)
else:
b_flag = arg
+def do_arg_actions():
+ '''do the actual action requested by the user'''
+ global b_flag
+ global status_flag
+ global force_flag
+ global args
+
if b_flag is None and not status_flag:
print "Error: No action specified for devices. Please give a -b or -u option"
print "Run '%s --usage' for further information" % sys.argv[0]
def main():
'''program main function'''
+ parse_args()
check_modules()
get_nic_details()
- parse_args()
+ do_arg_actions()
if __name__ == "__main__":
main()