xref: /dpdk/usertools/dpdk-devbind.py (revision df86b009)
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