xref: /dpdk/usertools/dpdk-devbind.py (revision 8fab26f8)
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}
52156c42eaSJerin Jacobcavium_pkx = {'Class': '08', 'Vendor': '177d', 'Device': 'a0dd,a049',
53156c42eaSJerin Jacob              'SVendor': None, 'SDevice': None}
548ad08a28SGuduri Prathyusha
55156c42eaSJerin Jacobnetwork_devices = [network_class, cavium_pkx]
568ad08a28SGuduri Prathyushacrypto_devices = [encryption_class, intel_processor_class]
5732a02dbfSGuduri Prathyushaeventdev_devices = [cavium_sso]
5880a1858dSGuduri Prathyushamempool_devices = [cavium_fpa]
59c6dab2a8SThomas Monjalon
60c6dab2a8SThomas Monjalon# global dict ethernet devices present. Dictionary indexed by PCI address.
61c6dab2a8SThomas Monjalon# Each device within this is itself a dictionary of device properties
62c6dab2a8SThomas Monjalondevices = {}
63c6dab2a8SThomas Monjalon# list of supported DPDK drivers
64c6dab2a8SThomas Monjalondpdk_drivers = ["igb_uio", "vfio-pci", "uio_pci_generic"]
65c6dab2a8SThomas Monjalon
66c6dab2a8SThomas Monjalon# command-line arg flags
67c6dab2a8SThomas Monjalonb_flag = None
68c6dab2a8SThomas Monjalonstatus_flag = False
69c6dab2a8SThomas Monjalonforce_flag = False
70c6dab2a8SThomas Monjalonargs = []
71c6dab2a8SThomas Monjalon
72c6dab2a8SThomas Monjalon
73c6dab2a8SThomas Monjalondef usage():
74c6dab2a8SThomas Monjalon    '''Print usage information for the program'''
75c6dab2a8SThomas Monjalon    argv0 = basename(sys.argv[0])
76c6dab2a8SThomas Monjalon    print("""
77c6dab2a8SThomas MonjalonUsage:
78c6dab2a8SThomas Monjalon------
79c6dab2a8SThomas Monjalon
80c6dab2a8SThomas Monjalon     %(argv0)s [options] DEVICE1 DEVICE2 ....
81c6dab2a8SThomas Monjalon
82c6dab2a8SThomas Monjalonwhere DEVICE1, DEVICE2 etc, are specified via PCI "domain:bus:slot.func" syntax
83c6dab2a8SThomas Monjalonor "bus:slot.func" syntax. For devices bound to Linux kernel drivers, they may
84c6dab2a8SThomas Monjalonalso be referred to by Linux interface name e.g. eth0, eth1, em0, em1, etc.
85c6dab2a8SThomas Monjalon
86c6dab2a8SThomas MonjalonOptions:
87c6dab2a8SThomas Monjalon    --help, --usage:
88c6dab2a8SThomas Monjalon        Display usage information and quit
89c6dab2a8SThomas Monjalon
90c6dab2a8SThomas Monjalon    -s, --status:
91b153c00bSFerruh Yigit        Print the current status of all known network, crypto, event
92b153c00bSFerruh Yigit        and mempool devices.
93c6dab2a8SThomas Monjalon        For each device, it displays the PCI domain, bus, slot and function,
94c6dab2a8SThomas Monjalon        along with a text description of the device. Depending upon whether the
95c6dab2a8SThomas Monjalon        device is being used by a kernel driver, the igb_uio driver, or no
96c6dab2a8SThomas Monjalon        driver, other relevant information will be displayed:
97c6dab2a8SThomas Monjalon        * the Linux interface name e.g. if=eth0
98c6dab2a8SThomas Monjalon        * the driver being used e.g. drv=igb_uio
99c6dab2a8SThomas Monjalon        * any suitable drivers not currently using that device
100c6dab2a8SThomas Monjalon            e.g. unused=igb_uio
101c6dab2a8SThomas Monjalon        NOTE: if this flag is passed along with a bind/unbind option, the
102c6dab2a8SThomas Monjalon        status display will always occur after the other operations have taken
103c6dab2a8SThomas Monjalon        place.
104c6dab2a8SThomas Monjalon
105b153c00bSFerruh Yigit    --status-dev:
106b153c00bSFerruh Yigit        Print the status of given device group. Supported device groups are:
107b153c00bSFerruh Yigit        "net", "crypto", "event" and "mempool"
108b153c00bSFerruh Yigit
109c6dab2a8SThomas Monjalon    -b driver, --bind=driver:
110c6dab2a8SThomas Monjalon        Select the driver to use or \"none\" to unbind the device
111c6dab2a8SThomas Monjalon
112c6dab2a8SThomas Monjalon    -u, --unbind:
113c6dab2a8SThomas Monjalon        Unbind a device (Equivalent to \"-b none\")
114c6dab2a8SThomas Monjalon
115c6dab2a8SThomas Monjalon    --force:
116c6dab2a8SThomas Monjalon        By default, network devices which are used by Linux - as indicated by
117c6dab2a8SThomas Monjalon        having routes in the routing table - cannot be modified. Using the
118c6dab2a8SThomas Monjalon        --force flag overrides this behavior, allowing active links to be
119c6dab2a8SThomas Monjalon        forcibly unbound.
120c6dab2a8SThomas Monjalon        WARNING: This can lead to loss of network connection and should be used
121c6dab2a8SThomas Monjalon        with caution.
122c6dab2a8SThomas Monjalon
123c6dab2a8SThomas MonjalonExamples:
124c6dab2a8SThomas Monjalon---------
125c6dab2a8SThomas Monjalon
126c6dab2a8SThomas MonjalonTo display current device status:
127c6dab2a8SThomas Monjalon        %(argv0)s --status
128c6dab2a8SThomas Monjalon
129b153c00bSFerruh YigitTo display current network device status:
130b153c00bSFerruh Yigit        %(argv0)s --status-dev net
131b153c00bSFerruh Yigit
132c6dab2a8SThomas MonjalonTo bind eth1 from the current driver and move to use igb_uio
133c6dab2a8SThomas Monjalon        %(argv0)s --bind=igb_uio eth1
134c6dab2a8SThomas Monjalon
135c6dab2a8SThomas MonjalonTo unbind 0000:01:00.0 from using any driver
136c6dab2a8SThomas Monjalon        %(argv0)s -u 0000:01:00.0
137c6dab2a8SThomas Monjalon
138c6dab2a8SThomas MonjalonTo bind 0000:02:00.0 and 0000:02:00.1 to the ixgbe kernel driver
139c6dab2a8SThomas Monjalon        %(argv0)s -b ixgbe 02:00.0 02:00.1
140c6dab2a8SThomas Monjalon
141c6dab2a8SThomas Monjalon    """ % locals())  # replace items from local variables
142c6dab2a8SThomas Monjalon
143c6dab2a8SThomas Monjalon
144c6dab2a8SThomas Monjalon# This is roughly compatible with check_output function in subprocess module
145c6dab2a8SThomas Monjalon# which is only available in python 2.7.
146c6dab2a8SThomas Monjalondef check_output(args, stderr=None):
147c6dab2a8SThomas Monjalon    '''Run a command and capture its output'''
148c6dab2a8SThomas Monjalon    return subprocess.Popen(args, stdout=subprocess.PIPE,
149c6dab2a8SThomas Monjalon                            stderr=stderr).communicate()[0]
150c6dab2a8SThomas Monjalon
151c6dab2a8SThomas Monjalon
152c6dab2a8SThomas Monjalondef find_module(mod):
153c6dab2a8SThomas Monjalon    '''find the .ko file for kernel module named mod.
154c6dab2a8SThomas Monjalon    Searches the $RTE_SDK/$RTE_TARGET directory, the kernel
155c6dab2a8SThomas Monjalon    modules directory and finally under the parent directory of
156c6dab2a8SThomas Monjalon    the script '''
157c6dab2a8SThomas Monjalon    # check $RTE_SDK/$RTE_TARGET directory
158c6dab2a8SThomas Monjalon    if 'RTE_SDK' in os.environ and 'RTE_TARGET' in os.environ:
159c6dab2a8SThomas Monjalon        path = "%s/%s/kmod/%s.ko" % (os.environ['RTE_SDK'],
160c6dab2a8SThomas Monjalon                                     os.environ['RTE_TARGET'], mod)
161c6dab2a8SThomas Monjalon        if exists(path):
162c6dab2a8SThomas Monjalon            return path
163c6dab2a8SThomas Monjalon
164c6dab2a8SThomas Monjalon    # check using depmod
165c6dab2a8SThomas Monjalon    try:
166df86b009SMark Asselstine        with open(os.devnull, "w") as fnull:
167df86b009SMark Asselstine            path = check_output(["modinfo", "-n", mod], stderr=fnull).strip()
168df86b009SMark Asselstine
169df86b009SMark Asselstine        if path and exists(path):
170c6dab2a8SThomas Monjalon            return path
171c6dab2a8SThomas Monjalon    except:  # if modinfo can't find module, it fails, so continue
172c6dab2a8SThomas Monjalon        pass
173c6dab2a8SThomas Monjalon
174c6dab2a8SThomas Monjalon    # check for a copy based off current path
175c6dab2a8SThomas Monjalon    tools_dir = dirname(abspath(sys.argv[0]))
176c6dab2a8SThomas Monjalon    if tools_dir.endswith("tools"):
177c6dab2a8SThomas Monjalon        base_dir = dirname(tools_dir)
178c6dab2a8SThomas Monjalon        find_out = check_output(["find", base_dir, "-name", mod + ".ko"])
179c6dab2a8SThomas Monjalon        if len(find_out) > 0:  # something matched
180c6dab2a8SThomas Monjalon            path = find_out.splitlines()[0]
181c6dab2a8SThomas Monjalon            if exists(path):
182c6dab2a8SThomas Monjalon                return path
183c6dab2a8SThomas Monjalon
184c6dab2a8SThomas Monjalon
185c6dab2a8SThomas Monjalondef check_modules():
186c6dab2a8SThomas Monjalon    '''Checks that igb_uio is loaded'''
187c6dab2a8SThomas Monjalon    global dpdk_drivers
188c6dab2a8SThomas Monjalon
189c6dab2a8SThomas Monjalon    # list of supported modules
190c6dab2a8SThomas Monjalon    mods = [{"Name": driver, "Found": False} for driver in dpdk_drivers]
191c6dab2a8SThomas Monjalon
192c6dab2a8SThomas Monjalon    # first check if module is loaded
193c6dab2a8SThomas Monjalon    try:
194c6dab2a8SThomas Monjalon        # Get list of sysfs modules (both built-in and dynamically loaded)
195c6dab2a8SThomas Monjalon        sysfs_path = '/sys/module/'
196c6dab2a8SThomas Monjalon
197c6dab2a8SThomas Monjalon        # Get the list of directories in sysfs_path
198c6dab2a8SThomas Monjalon        sysfs_mods = [os.path.join(sysfs_path, o) for o
199c6dab2a8SThomas Monjalon                      in os.listdir(sysfs_path)
200c6dab2a8SThomas Monjalon                      if os.path.isdir(os.path.join(sysfs_path, o))]
201c6dab2a8SThomas Monjalon
202c6dab2a8SThomas Monjalon        # Extract the last element of '/sys/module/abc' in the array
203c6dab2a8SThomas Monjalon        sysfs_mods = [a.split('/')[-1] for a in sysfs_mods]
204c6dab2a8SThomas Monjalon
205c6dab2a8SThomas Monjalon        # special case for vfio_pci (module is named vfio-pci,
206c6dab2a8SThomas Monjalon        # but its .ko is named vfio_pci)
207*8fab26f8SOmri Mor        sysfs_mods = [a if a != 'vfio_pci' else 'vfio-pci' for a in sysfs_mods]
208c6dab2a8SThomas Monjalon
209c6dab2a8SThomas Monjalon        for mod in mods:
210c6dab2a8SThomas Monjalon            if mod["Name"] in sysfs_mods:
211c6dab2a8SThomas Monjalon                mod["Found"] = True
212c6dab2a8SThomas Monjalon    except:
213c6dab2a8SThomas Monjalon        pass
214c6dab2a8SThomas Monjalon
215c6dab2a8SThomas Monjalon    # check if we have at least one loaded module
216c6dab2a8SThomas Monjalon    if True not in [mod["Found"] for mod in mods] and b_flag is not None:
217c6dab2a8SThomas Monjalon        if b_flag in dpdk_drivers:
218c6dab2a8SThomas Monjalon            print("Error - no supported modules(DPDK driver) are loaded")
219c6dab2a8SThomas Monjalon            sys.exit(1)
220c6dab2a8SThomas Monjalon        else:
221c6dab2a8SThomas Monjalon            print("Warning - no supported modules(DPDK driver) are loaded")
222c6dab2a8SThomas Monjalon
223c6dab2a8SThomas Monjalon    # change DPDK driver list to only contain drivers that are loaded
224c6dab2a8SThomas Monjalon    dpdk_drivers = [mod["Name"] for mod in mods if mod["Found"]]
225c6dab2a8SThomas Monjalon
226c6dab2a8SThomas Monjalon
227c6dab2a8SThomas Monjalondef has_driver(dev_id):
228c6dab2a8SThomas Monjalon    '''return true if a device is assigned to a driver. False otherwise'''
229c6dab2a8SThomas Monjalon    return "Driver_str" in devices[dev_id]
230c6dab2a8SThomas Monjalon
231c6dab2a8SThomas Monjalon
232c3ce205dSGuduri Prathyushadef get_pci_device_details(dev_id, probe_lspci):
233c6dab2a8SThomas Monjalon    '''This function gets additional details for a PCI device'''
234c6dab2a8SThomas Monjalon    device = {}
235c6dab2a8SThomas Monjalon
236c3ce205dSGuduri Prathyusha    if probe_lspci:
237c6dab2a8SThomas Monjalon        extra_info = check_output(["lspci", "-vmmks", dev_id]).splitlines()
238c6dab2a8SThomas Monjalon
239c6dab2a8SThomas Monjalon        # parse lspci details
240c6dab2a8SThomas Monjalon        for line in extra_info:
241c6dab2a8SThomas Monjalon            if len(line) == 0:
242c6dab2a8SThomas Monjalon                continue
243c6dab2a8SThomas Monjalon            name, value = line.decode().split("\t", 1)
244c6dab2a8SThomas Monjalon            name = name.strip(":") + "_str"
245c6dab2a8SThomas Monjalon            device[name] = value
246c6dab2a8SThomas Monjalon    # check for a unix interface name
247c6dab2a8SThomas Monjalon    device["Interface"] = ""
248c6dab2a8SThomas Monjalon    for base, dirs, _ in os.walk("/sys/bus/pci/devices/%s/" % dev_id):
249c6dab2a8SThomas Monjalon        if "net" in dirs:
250c6dab2a8SThomas Monjalon            device["Interface"] = \
251c6dab2a8SThomas Monjalon                ",".join(os.listdir(os.path.join(base, "net")))
252c6dab2a8SThomas Monjalon            break
253c6dab2a8SThomas Monjalon    # check if a port is used for ssh connection
254c6dab2a8SThomas Monjalon    device["Ssh_if"] = False
255c6dab2a8SThomas Monjalon    device["Active"] = ""
256c6dab2a8SThomas Monjalon
257c6dab2a8SThomas Monjalon    return device
258c6dab2a8SThomas Monjalon
259ea9f00f7SGuduri Prathyushadef clear_data():
260ea9f00f7SGuduri Prathyusha    '''This function clears any old data'''
261ea9f00f7SGuduri Prathyusha    devices = {}
262c6dab2a8SThomas Monjalon
263ea9f00f7SGuduri Prathyushadef get_device_details(devices_type):
264c6dab2a8SThomas Monjalon    '''This function populates the "devices" dictionary. The keys used are
265c6dab2a8SThomas Monjalon    the pci addresses (domain:bus:slot.func). The values are themselves
266c6dab2a8SThomas Monjalon    dictionaries - one for each NIC.'''
267c6dab2a8SThomas Monjalon    global devices
268c6dab2a8SThomas Monjalon    global dpdk_drivers
269c6dab2a8SThomas Monjalon
270c6dab2a8SThomas Monjalon    # first loop through and read details for all devices
271c3ce205dSGuduri Prathyusha    # request machine readable format, with numeric IDs and String
272c6dab2a8SThomas Monjalon    dev = {}
273c3ce205dSGuduri Prathyusha    dev_lines = check_output(["lspci", "-Dvmmnnk"]).splitlines()
274c6dab2a8SThomas Monjalon    for dev_line in dev_lines:
275c6dab2a8SThomas Monjalon        if len(dev_line) == 0:
2768ad08a28SGuduri Prathyusha            if device_type_match(dev, devices_type):
2778ad08a28SGuduri Prathyusha                # Replace "Driver" with "Driver_str" to have consistency of
2788ad08a28SGuduri Prathyusha                # of dictionary key names
279c3ce205dSGuduri Prathyusha                if "Driver" in dev.keys():
280c3ce205dSGuduri Prathyusha                    dev["Driver_str"] = dev.pop("Driver")
281c6dab2a8SThomas Monjalon                # use dict to make copy of dev
282c6dab2a8SThomas Monjalon                devices[dev["Slot"]] = dict(dev)
283c3ce205dSGuduri Prathyusha            # Clear previous device's data
284c3ce205dSGuduri Prathyusha            dev = {}
285c6dab2a8SThomas Monjalon        else:
286c6dab2a8SThomas Monjalon            name, value = dev_line.decode().split("\t", 1)
287c3ce205dSGuduri Prathyusha            value_list = value.rsplit(' ', 1)
288c3ce205dSGuduri Prathyusha            if len(value_list) > 1:
289c3ce205dSGuduri Prathyusha                # String stored in <name>_str
290c3ce205dSGuduri Prathyusha                dev[name.rstrip(":") + '_str'] = value_list[0]
291c3ce205dSGuduri Prathyusha            # Numeric IDs
292c3ce205dSGuduri Prathyusha            dev[name.rstrip(":")] = value_list[len(value_list) - 1] \
293c3ce205dSGuduri Prathyusha                .rstrip("]").lstrip("[")
294c6dab2a8SThomas Monjalon
2958ad08a28SGuduri Prathyusha    if devices_type == network_devices:
296c6dab2a8SThomas Monjalon        # check what is the interface if any for an ssh connection if
297c6dab2a8SThomas Monjalon        # any to this host, so we can mark it later.
298c6dab2a8SThomas Monjalon        ssh_if = []
299c6dab2a8SThomas Monjalon        route = check_output(["ip", "-o", "route"])
300c6dab2a8SThomas Monjalon        # filter out all lines for 169.254 routes
301c6dab2a8SThomas Monjalon        route = "\n".join(filter(lambda ln: not ln.startswith("169.254"),
302c6dab2a8SThomas Monjalon                             route.decode().splitlines()))
303c6dab2a8SThomas Monjalon        rt_info = route.split()
304c6dab2a8SThomas Monjalon        for i in range(len(rt_info) - 1):
305c6dab2a8SThomas Monjalon            if rt_info[i] == "dev":
306c6dab2a8SThomas Monjalon                ssh_if.append(rt_info[i+1])
307c6dab2a8SThomas Monjalon
308c6dab2a8SThomas Monjalon    # based on the basic info, get extended text details
309c6dab2a8SThomas Monjalon    for d in devices.keys():
3108ad08a28SGuduri Prathyusha        if not device_type_match(devices[d], devices_type):
311617d9052SYoni Gilad            continue
312617d9052SYoni Gilad
313c6dab2a8SThomas Monjalon        # get additional info and add it to existing data
314c6dab2a8SThomas Monjalon        devices[d] = devices[d].copy()
315c3ce205dSGuduri Prathyusha        # No need to probe lspci
316c3ce205dSGuduri Prathyusha        devices[d].update(get_pci_device_details(d, False).items())
317c6dab2a8SThomas Monjalon
3188ad08a28SGuduri Prathyusha        if devices_type == network_devices:
319ea9f00f7SGuduri Prathyusha            for _if in ssh_if:
320ea9f00f7SGuduri Prathyusha                if _if in devices[d]["Interface"].split(","):
321ea9f00f7SGuduri Prathyusha                    devices[d]["Ssh_if"] = True
322ea9f00f7SGuduri Prathyusha                    devices[d]["Active"] = "*Active*"
323ea9f00f7SGuduri Prathyusha                    break
324ea9f00f7SGuduri Prathyusha
325c6dab2a8SThomas Monjalon        # add igb_uio to list of supporting modules if needed
326c6dab2a8SThomas Monjalon        if "Module_str" in devices[d]:
327c6dab2a8SThomas Monjalon            for driver in dpdk_drivers:
328c6dab2a8SThomas Monjalon                if driver not in devices[d]["Module_str"]:
329c6dab2a8SThomas Monjalon                    devices[d]["Module_str"] = \
330c6dab2a8SThomas Monjalon                        devices[d]["Module_str"] + ",%s" % driver
331c6dab2a8SThomas Monjalon        else:
332c6dab2a8SThomas Monjalon            devices[d]["Module_str"] = ",".join(dpdk_drivers)
333c6dab2a8SThomas Monjalon
334c6dab2a8SThomas Monjalon        # make sure the driver and module strings do not have any duplicates
335c6dab2a8SThomas Monjalon        if has_driver(d):
336c6dab2a8SThomas Monjalon            modules = devices[d]["Module_str"].split(",")
337c6dab2a8SThomas Monjalon            if devices[d]["Driver_str"] in modules:
338c6dab2a8SThomas Monjalon                modules.remove(devices[d]["Driver_str"])
339c6dab2a8SThomas Monjalon                devices[d]["Module_str"] = ",".join(modules)
340c6dab2a8SThomas Monjalon
341c6dab2a8SThomas Monjalon
3428ad08a28SGuduri Prathyushadef device_type_match(dev, devices_type):
3438ad08a28SGuduri Prathyusha    for i in range(len(devices_type)):
3448ad08a28SGuduri Prathyusha        param_count = len(
3458ad08a28SGuduri Prathyusha            [x for x in devices_type[i].values() if x is not None])
3468ad08a28SGuduri Prathyusha        match_count = 0
3478ad08a28SGuduri Prathyusha        if dev["Class"][0:2] == devices_type[i]["Class"]:
3488ad08a28SGuduri Prathyusha            match_count = match_count + 1
3498ad08a28SGuduri Prathyusha            for key in devices_type[i].keys():
3508ad08a28SGuduri Prathyusha                if key != 'Class' and devices_type[i][key]:
3518ad08a28SGuduri Prathyusha                    value_list = devices_type[i][key].split(',')
3528ad08a28SGuduri Prathyusha                    for value in value_list:
3538ad08a28SGuduri Prathyusha                        if value.strip(' ') == dev[key]:
3548ad08a28SGuduri Prathyusha                            match_count = match_count + 1
3558ad08a28SGuduri Prathyusha            # count must be the number of non None parameters to match
3568ad08a28SGuduri Prathyusha            if match_count == param_count:
3578ad08a28SGuduri Prathyusha                return True
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"""
520657c7133SFerruh Yigit
521657c7133SFerruh Yigit    if dev_list[0] == "dpdk":
522657c7133SFerruh Yigit        for d in devices.keys():
523657c7133SFerruh Yigit            if "Driver_str" in devices[d]:
524657c7133SFerruh Yigit                if devices[d]["Driver_str"] in dpdk_drivers:
525657c7133SFerruh Yigit                    unbind_one(devices[d]["Slot"], force)
526657c7133SFerruh Yigit        return
527657c7133SFerruh Yigit
528c6dab2a8SThomas Monjalon    dev_list = map(dev_id_from_dev_name, dev_list)
529c6dab2a8SThomas Monjalon    for d in dev_list:
530c6dab2a8SThomas Monjalon        unbind_one(d, force)
531c6dab2a8SThomas Monjalon
532c6dab2a8SThomas Monjalon
533c6dab2a8SThomas Monjalondef bind_all(dev_list, driver, force=False):
534c6dab2a8SThomas Monjalon    """Bind method, takes a list of device locations"""
535c6dab2a8SThomas Monjalon    global devices
536c6dab2a8SThomas Monjalon
537c6dab2a8SThomas Monjalon    dev_list = map(dev_id_from_dev_name, dev_list)
538c6dab2a8SThomas Monjalon
539c6dab2a8SThomas Monjalon    for d in dev_list:
540c6dab2a8SThomas Monjalon        bind_one(d, driver, force)
541c6dab2a8SThomas Monjalon
5422fc35029SGuduri Prathyusha    # For kenels < 3.15 when binding devices to a generic driver
5432fc35029SGuduri Prathyusha    # (i.e. one that doesn't have a PCI ID table) using new_id, some devices
5442fc35029SGuduri Prathyusha    # that are not bound to any other driver could be bound even if no one has
5452fc35029SGuduri Prathyusha    # asked them to. hence, we check the list of drivers again, and see if
5462fc35029SGuduri Prathyusha    # some of the previously-unbound devices were erroneously bound.
5472fc35029SGuduri Prathyusha    if not os.path.exists("/sys/bus/pci/devices/%s/driver_override" % d):
548c6dab2a8SThomas Monjalon        for d in devices.keys():
549c6dab2a8SThomas Monjalon            # skip devices that were already bound or that we know should be bound
550c6dab2a8SThomas Monjalon            if "Driver_str" in devices[d] or d in dev_list:
551c6dab2a8SThomas Monjalon                continue
552c6dab2a8SThomas Monjalon
553c6dab2a8SThomas Monjalon            # update information about this device
554c6dab2a8SThomas Monjalon            devices[d] = dict(devices[d].items() +
555c3ce205dSGuduri Prathyusha                              get_pci_device_details(d, True).items())
556c6dab2a8SThomas Monjalon
557c6dab2a8SThomas Monjalon            # check if updated information indicates that the device was bound
558c6dab2a8SThomas Monjalon            if "Driver_str" in devices[d]:
559c6dab2a8SThomas Monjalon                unbind_one(d, force)
560c6dab2a8SThomas Monjalon
561c6dab2a8SThomas Monjalon
562c6dab2a8SThomas Monjalondef display_devices(title, dev_list, extra_params=None):
563c6dab2a8SThomas Monjalon    '''Displays to the user the details of a list of devices given in
564c6dab2a8SThomas Monjalon    "dev_list". The "extra_params" parameter, if given, should contain a string
565c6dab2a8SThomas Monjalon     with %()s fields in it for replacement by the named fields in each
566c6dab2a8SThomas Monjalon     device's dictionary.'''
567c6dab2a8SThomas Monjalon    strings = []  # this holds the strings to print. We sort before printing
568c6dab2a8SThomas Monjalon    print("\n%s" % title)
569c6dab2a8SThomas Monjalon    print("="*len(title))
570c6dab2a8SThomas Monjalon    if len(dev_list) == 0:
571c6dab2a8SThomas Monjalon        strings.append("<none>")
572c6dab2a8SThomas Monjalon    else:
573c6dab2a8SThomas Monjalon        for dev in dev_list:
574c6dab2a8SThomas Monjalon            if extra_params is not None:
575c3ce205dSGuduri Prathyusha                strings.append("%s '%s %s' %s" % (dev["Slot"],
576c6dab2a8SThomas Monjalon                                               dev["Device_str"],
577c3ce205dSGuduri Prathyusha                                               dev["Device"],
578c6dab2a8SThomas Monjalon                                               extra_params % dev))
579c6dab2a8SThomas Monjalon            else:
580c6dab2a8SThomas Monjalon                strings.append("%s '%s'" % (dev["Slot"], dev["Device_str"]))
581c6dab2a8SThomas Monjalon    # sort before printing, so that the entries appear in PCI order
582c6dab2a8SThomas Monjalon    strings.sort()
583c6dab2a8SThomas Monjalon    print("\n".join(strings))  # print one per line
584c6dab2a8SThomas Monjalon
585c7dd412bSGuduri Prathyushadef show_device_status(devices_type, device_name):
586c6dab2a8SThomas Monjalon    global dpdk_drivers
587c6dab2a8SThomas Monjalon    kernel_drv = []
588c6dab2a8SThomas Monjalon    dpdk_drv = []
589c6dab2a8SThomas Monjalon    no_drv = []
590c6dab2a8SThomas Monjalon
591c6dab2a8SThomas Monjalon    # split our list of network devices into the three categories above
592c6dab2a8SThomas Monjalon    for d in devices.keys():
5938ad08a28SGuduri Prathyusha        if device_type_match(devices[d], devices_type):
594c6dab2a8SThomas Monjalon            if not has_driver(d):
595c6dab2a8SThomas Monjalon                no_drv.append(devices[d])
596c6dab2a8SThomas Monjalon                continue
597c6dab2a8SThomas Monjalon            if devices[d]["Driver_str"] in dpdk_drivers:
598c6dab2a8SThomas Monjalon                dpdk_drv.append(devices[d])
599c6dab2a8SThomas Monjalon            else:
600c6dab2a8SThomas Monjalon                kernel_drv.append(devices[d])
601c6dab2a8SThomas Monjalon
602c6dab2a8SThomas Monjalon    # print each category separately, so we can clearly see what's used by DPDK
6038ad08a28SGuduri Prathyusha    display_devices("%s devices using DPDK-compatible driver" % device_name,
6048ad08a28SGuduri Prathyusha                    dpdk_drv, "drv=%(Driver_str)s unused=%(Module_str)s")
605c7dd412bSGuduri Prathyusha    display_devices("%s devices using kernel driver" % device_name, kernel_drv,
606c6dab2a8SThomas Monjalon                    "if=%(Interface)s drv=%(Driver_str)s "
607c6dab2a8SThomas Monjalon                    "unused=%(Module_str)s %(Active)s")
6088ad08a28SGuduri Prathyusha    display_devices("Other %s devices" % device_name, no_drv,
6098ad08a28SGuduri Prathyusha                    "unused=%(Module_str)s")
610c6dab2a8SThomas Monjalon
611c7dd412bSGuduri Prathyushadef show_status():
612c7dd412bSGuduri Prathyusha    '''Function called when the script is passed the "--status" option.
613c7dd412bSGuduri Prathyusha    Displays to the user what devices are bound to the igb_uio driver, the
614c7dd412bSGuduri Prathyusha    kernel driver or to no driver'''
615c6dab2a8SThomas Monjalon
616b153c00bSFerruh Yigit    if status_dev == "net" or status_dev == "all":
617c7dd412bSGuduri Prathyusha        show_device_status(network_devices, "Network")
618b153c00bSFerruh Yigit
619b153c00bSFerruh Yigit    if status_dev == "crypto" or status_dev == "all":
620c7dd412bSGuduri Prathyusha        show_device_status(crypto_devices, "Crypto")
621b153c00bSFerruh Yigit
622b153c00bSFerruh Yigit    if status_dev == "event" or status_dev == "all":
62332a02dbfSGuduri Prathyusha        show_device_status(eventdev_devices, "Eventdev")
624b153c00bSFerruh Yigit
625b153c00bSFerruh Yigit    if status_dev == "mempool" or status_dev == "all":
62680a1858dSGuduri Prathyusha        show_device_status(mempool_devices, "Mempool")
627c6dab2a8SThomas Monjalon
628c6dab2a8SThomas Monjalondef parse_args():
629c6dab2a8SThomas Monjalon    '''Parses the command-line arguments given by the user and takes the
630c6dab2a8SThomas Monjalon    appropriate action for each'''
631c6dab2a8SThomas Monjalon    global b_flag
632c6dab2a8SThomas Monjalon    global status_flag
633b153c00bSFerruh Yigit    global status_dev
634c6dab2a8SThomas Monjalon    global force_flag
635c6dab2a8SThomas Monjalon    global args
636c6dab2a8SThomas Monjalon    if len(sys.argv) <= 1:
637c6dab2a8SThomas Monjalon        usage()
638c6dab2a8SThomas Monjalon        sys.exit(0)
639c6dab2a8SThomas Monjalon
640c6dab2a8SThomas Monjalon    try:
641c6dab2a8SThomas Monjalon        opts, args = getopt.getopt(sys.argv[1:], "b:us",
642b153c00bSFerruh Yigit                                   ["help", "usage", "status", "status-dev=",
643b153c00bSFerruh Yigit                                    "force", "bind=", "unbind", ])
644c6dab2a8SThomas Monjalon    except getopt.GetoptError as error:
645c6dab2a8SThomas Monjalon        print(str(error))
646c6dab2a8SThomas Monjalon        print("Run '%s --usage' for further information" % sys.argv[0])
647c6dab2a8SThomas Monjalon        sys.exit(1)
648c6dab2a8SThomas Monjalon
649c6dab2a8SThomas Monjalon    for opt, arg in opts:
650c6dab2a8SThomas Monjalon        if opt == "--help" or opt == "--usage":
651c6dab2a8SThomas Monjalon            usage()
652c6dab2a8SThomas Monjalon            sys.exit(0)
653b153c00bSFerruh Yigit        if opt == "--status-dev":
654b153c00bSFerruh Yigit            status_flag = True
655b153c00bSFerruh Yigit            status_dev = arg
656c6dab2a8SThomas Monjalon        if opt == "--status" or opt == "-s":
657c6dab2a8SThomas Monjalon            status_flag = True
658b153c00bSFerruh Yigit            status_dev = "all"
659c6dab2a8SThomas Monjalon        if opt == "--force":
660c6dab2a8SThomas Monjalon            force_flag = True
661c6dab2a8SThomas Monjalon        if opt == "-b" or opt == "-u" or opt == "--bind" or opt == "--unbind":
662c6dab2a8SThomas Monjalon            if b_flag is not None:
663c6dab2a8SThomas Monjalon                print("Error - Only one bind or unbind may be specified\n")
664c6dab2a8SThomas Monjalon                sys.exit(1)
665c6dab2a8SThomas Monjalon            if opt == "-u" or opt == "--unbind":
666c6dab2a8SThomas Monjalon                b_flag = "none"
667c6dab2a8SThomas Monjalon            else:
668c6dab2a8SThomas Monjalon                b_flag = arg
669c6dab2a8SThomas Monjalon
670c6dab2a8SThomas Monjalon
671c6dab2a8SThomas Monjalondef do_arg_actions():
672c6dab2a8SThomas Monjalon    '''do the actual action requested by the user'''
673c6dab2a8SThomas Monjalon    global b_flag
674c6dab2a8SThomas Monjalon    global status_flag
675c6dab2a8SThomas Monjalon    global force_flag
676c6dab2a8SThomas Monjalon    global args
677c6dab2a8SThomas Monjalon
678c6dab2a8SThomas Monjalon    if b_flag is None and not status_flag:
679c6dab2a8SThomas Monjalon        print("Error: No action specified for devices."
680c6dab2a8SThomas Monjalon              "Please give a -b or -u option")
681c6dab2a8SThomas Monjalon        print("Run '%s --usage' for further information" % sys.argv[0])
682c6dab2a8SThomas Monjalon        sys.exit(1)
683c6dab2a8SThomas Monjalon
684c6dab2a8SThomas Monjalon    if b_flag is not None and len(args) == 0:
685c6dab2a8SThomas Monjalon        print("Error: No devices specified.")
686c6dab2a8SThomas Monjalon        print("Run '%s --usage' for further information" % sys.argv[0])
687c6dab2a8SThomas Monjalon        sys.exit(1)
688c6dab2a8SThomas Monjalon
689c6dab2a8SThomas Monjalon    if b_flag == "none" or b_flag == "None":
690c6dab2a8SThomas Monjalon        unbind_all(args, force_flag)
691c6dab2a8SThomas Monjalon    elif b_flag is not None:
692c6dab2a8SThomas Monjalon        bind_all(args, b_flag, force_flag)
693c6dab2a8SThomas Monjalon    if status_flag:
694c6dab2a8SThomas Monjalon        if b_flag is not None:
695ea9f00f7SGuduri Prathyusha            clear_data()
6968ad08a28SGuduri Prathyusha            # refresh if we have changed anything
6978ad08a28SGuduri Prathyusha            get_device_details(network_devices)
6988ad08a28SGuduri Prathyusha            get_device_details(crypto_devices)
69932a02dbfSGuduri Prathyusha            get_device_details(eventdev_devices)
70080a1858dSGuduri Prathyusha            get_device_details(mempool_devices)
701c6dab2a8SThomas Monjalon        show_status()
702c6dab2a8SThomas Monjalon
703c6dab2a8SThomas Monjalon
704c6dab2a8SThomas Monjalondef main():
705c6dab2a8SThomas Monjalon    '''program main function'''
706c6dab2a8SThomas Monjalon    parse_args()
707c6dab2a8SThomas Monjalon    check_modules()
708ea9f00f7SGuduri Prathyusha    clear_data()
7098ad08a28SGuduri Prathyusha    get_device_details(network_devices)
7108ad08a28SGuduri Prathyusha    get_device_details(crypto_devices)
71132a02dbfSGuduri Prathyusha    get_device_details(eventdev_devices)
71280a1858dSGuduri Prathyusha    get_device_details(mempool_devices)
713c6dab2a8SThomas Monjalon    do_arg_actions()
714c6dab2a8SThomas Monjalon
715c6dab2a8SThomas Monjalonif __name__ == "__main__":
716c6dab2a8SThomas Monjalon    main()
717