summaryrefslogtreecommitdiffstats
path: root/extras/vpp_config/vpplib/VppPCIUtil.py
diff options
context:
space:
mode:
Diffstat (limited to 'extras/vpp_config/vpplib/VppPCIUtil.py')
-rw-r--r--extras/vpp_config/vpplib/VppPCIUtil.py330
1 files changed, 330 insertions, 0 deletions
diff --git a/extras/vpp_config/vpplib/VppPCIUtil.py b/extras/vpp_config/vpplib/VppPCIUtil.py
new file mode 100644
index 00000000000..829d66ae374
--- /dev/null
+++ b/extras/vpp_config/vpplib/VppPCIUtil.py
@@ -0,0 +1,330 @@
+# Copyright (c) 2016 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""VPP PCI Utility libraries"""
+
+import re
+
+from vpplib.VPPUtil import VPPUtil
+
+DPDK_SCRIPT = "/vpp/vpp-config/scripts/dpdk-devbind.py"
+
+# PCI Device id regular expresssion
+PCI_DEV_ID_REGEX = '[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+.[0-9A-Fa-f]+'
+
+
+class VppPCIUtil(object):
+ """
+ PCI Utilities
+
+ """
+
+ @staticmethod
+ def _create_device_list(device_string):
+ """
+ Returns a list of PCI devices
+
+ :param device_string: The devices string from dpdk_devbind
+ :returns: The device list
+ :rtype: dictionary
+ """
+
+ devices = {}
+
+ ids = re.findall(PCI_DEV_ID_REGEX, device_string)
+ descriptions = re.findall(r'\'([\s\S]*?)\'', device_string)
+ unused = re.findall(r'unused=[\w,]+', device_string)
+
+ for i, j in enumerate(ids):
+ device = {'description': descriptions[i]}
+ if unused:
+ device['unused'] = unused[i].split('=')[1].split(',')
+
+ cmd = 'ls /sys/bus/pci/devices/{}/driver/module/drivers'. \
+ format(ids[i])
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret == 0:
+ device['driver'] = stdout.split(':')[1].rstrip('\n')
+
+ cmd = 'cat /sys/bus/pci/devices/{}/numa_node'.format(ids[i])
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError('{} failed {} {}'.
+ format(cmd, stderr, stdout))
+ numa_node = stdout.rstrip('\n')
+ if numa_node == '-1':
+ device['numa_node'] = '0'
+ else:
+ device['numa_node'] = numa_node
+
+ interfaces = []
+ device['interfaces'] = []
+ cmd = 'ls /sys/bus/pci/devices/{}/net'.format(ids[i])
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret == 0:
+ interfaces = stdout.rstrip('\n').split()
+ device['interfaces'] = interfaces
+
+ l2_addrs = []
+ for intf in interfaces:
+ cmd = 'cat /sys/bus/pci/devices/{}/net/{}/address'.format(
+ ids[i], intf)
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError('{} failed {} {}'.
+ format(cmd, stderr, stdout))
+
+ l2_addrs.append(stdout.rstrip('\n'))
+
+ device['l2addr'] = l2_addrs
+
+ devices[ids[i]] = device
+
+ return devices
+
+ def __init__(self, node):
+ self._node = node
+ self._dpdk_devices = {}
+ self._kernel_devices = {}
+ self._other_devices = {}
+ self._crypto_dpdk_devices = {}
+ self._crypto_kernel_devices = {}
+ self._crypto_other_devices = {}
+ self._link_up_devices = {}
+
+ def get_all_devices(self):
+ """
+ Returns a list of all the devices
+
+ """
+
+ node = self._node
+ rootdir = node['rootdir']
+ dpdk_script = rootdir + DPDK_SCRIPT
+ cmd = dpdk_script + ' --status'
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError('{} failed on node {} {}'.format(
+ cmd,
+ node['host'],
+ stderr))
+
+ # Get the network devices using the DPDK
+ # First get everything after using DPDK
+ stda = stdout.split('Network devices using DPDK-compatible driver')[1]
+ # Then get everything before using kernel driver
+ using_dpdk = stda.split('Network devices using kernel driver')[0]
+ self._dpdk_devices = self._create_device_list(using_dpdk)
+
+ # Get the network devices using the kernel
+ stda = stdout.split('Network devices using kernel driver')[1]
+ using_kernel = stda.split('Other network devices')[0]
+ self._kernel_devices = self._create_device_list(using_kernel)
+
+ # Get the other network devices
+ stda = stdout.split('Other network devices')[1]
+ other = stda.split('Crypto devices using DPDK-compatible driver')[0]
+ self._other_devices = self._create_device_list(other)
+
+ # Get the crypto devices using the DPDK
+ stda = stdout.split('Crypto devices using DPDK-compatible driver')[1]
+ crypto_using_dpdk = stda.split('Crypto devices using kernel driver')[0]
+ self._crypto_dpdk_devices = self._create_device_list(
+ crypto_using_dpdk)
+
+ # Get the network devices using the kernel
+ stda = stdout.split('Crypto devices using kernel driver')[1]
+ crypto_using_kernel = stda.split('Other crypto devices')[0]
+ self._crypto_kernel_devices = self._create_device_list(
+ crypto_using_kernel)
+
+ # Get the other network devices
+ crypto_other = stdout.split('Other crypto devices')[1]
+ self._crypto_other_devices = self._create_device_list(crypto_other)
+
+ # Get the devices used by the kernel
+ for devk in self._kernel_devices.items():
+ dvid = devk[0]
+ device = devk[1]
+ for i in device['interfaces']:
+ cmd = "ip addr show " + i
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError('{} failed on node {} {}'.format(
+ cmd,
+ node['host'],
+ stderr))
+ lstate = re.findall(r'state \w+', stdout)[0].split(' ')[1]
+
+ # Take care of the links that are UP
+ if lstate == 'UP':
+ device['linkup'] = True
+ self._link_up_devices[dvid] = device
+
+ for devl in self._link_up_devices.items():
+ dvid = devl[0]
+ del self._kernel_devices[dvid]
+
+ def get_dpdk_devices(self):
+ """
+ Returns a list the dpdk devices
+
+ """
+ return self._dpdk_devices
+
+ def get_kernel_devices(self):
+ """
+ Returns a list the kernel devices
+
+ """
+ return self._kernel_devices
+
+ def get_other_devices(self):
+ """
+ Returns a list the other devices
+
+ """
+ return self._other_devices
+
+ def get_crypto_dpdk_devices(self):
+ """
+ Returns a list the crypto dpdk devices
+
+ """
+ return self._crypto_dpdk_devices
+
+ def get_crypto_kernel_devices(self):
+ """
+ Returns a list the crypto kernel devices
+
+ """
+ return self._crypto_kernel_devices
+
+ def get_crypto_other_devices(self):
+ """
+ Returns a list the crypto other devices
+
+ """
+ return self._crypto_other_devices
+
+ def get_link_up_devices(self):
+ """
+ Returns a list the link up devices
+
+ """
+ return self._link_up_devices
+
+ @staticmethod
+ def vpp_create_interface(interfaces, device_id, device):
+ """
+ Create an interface using the device is and device
+
+ """
+
+ name = 'port' + str(len(interfaces))
+ interfaces[name] = {}
+ interfaces[name]['pci_address'] = device_id
+ interfaces[name]['numa_node'] = device['numa_node']
+ if 'l2addr' in device:
+ l2_addrs = device['l2addr']
+ for i, j in enumerate(l2_addrs):
+ if i > 0:
+ mname = 'mac_address' + str(i + 1)
+ interfaces[name][mname] = l2_addrs[i]
+ else:
+ interfaces[name]['mac_address'] = l2_addrs[i]
+
+ @staticmethod
+ def show_vpp_devices(devices, show_interfaces=True, show_header=True):
+ """
+ show the vpp devices specified in the argument
+
+ :param devices: A list of devices
+ :param show_interfaces: show the kernel information
+ :type devices: dict
+ :type show_interfaces: bool
+ """
+
+
+ if show_interfaces:
+ header = "{:15} {:25} {:50}".format("PCI ID",
+ "Kernel Interface(s)",
+ "Description")
+ else:
+ header = "{:15} {:50}".format("PCI ID",
+ "Description")
+ dashseparator = ("-" * (len(header) - 2))
+
+
+ if show_header == True:
+ print header
+ print dashseparator
+ for dit in devices.items():
+ dvid = dit[0]
+ device = dit[1]
+ if show_interfaces:
+ interfaces = device['interfaces']
+ interface = ''
+ for i, j in enumerate(interfaces):
+ if i > 0:
+ interface += ',' + interfaces[i]
+ else:
+ interface = interfaces[i]
+
+ print "{:15} {:25} {:50}".format(
+ dvid, interface, device['description'])
+ else:
+ print "{:15} {:50}".format(
+ dvid, device['description'])
+
+ @staticmethod
+ def unbind_vpp_device(node, device_id):
+ """
+ unbind the device specified
+
+ :param node: Node dictionary with cpuinfo.
+ :param device_id: The device id
+ :type node: dict
+ :type device_id: string
+ """
+
+
+ rootdir = node['rootdir']
+ dpdk_script = rootdir + DPDK_SCRIPT
+ cmd = dpdk_script + ' -u ' + ' ' + device_id
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError('{} failed on node {} {} {}'.format(
+ cmd, node['host'],
+ stdout, stderr))
+
+ @staticmethod
+ def bind_vpp_device(node, driver, device_id):
+ """
+ bind the device specified
+
+ :param node: Node dictionary with cpuinfo.
+ :param driver: The driver
+ :param device_id: The device id
+ :type node: dict
+ :type driver: string
+ :type device_id: string
+ """
+
+ rootdir = node['rootdir']
+ dpdk_script = rootdir + DPDK_SCRIPT
+ cmd = dpdk_script + ' -b ' + driver + ' ' + device_id
+ (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
+ if ret != 0:
+ raise RuntimeError('{} failed on node {} {} {}'.format(
+ cmd, node['host'], stdout, stderr))