bugfix: mount hugepages for PVP and PVVP scenarios
[vswitchperf.git] / src / dpdk / dpdk.py
index 9b3d138..f2f6ec9 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2016 Intel Corporation.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 
 """Automation of system configuration for DPDK use.
 
-Parts of this based on ``tools/pci_unbind.py`` script from Intel(R) DPDK.
+Parts of this based on ``tools/dpdk_nic_bind.py`` script from Intel(R)
+DPDK.
 """
 
 from sys import platform as _platform
 
 import os
-import re
 import subprocess
 import logging
 import locale
 
 from tools import tasks
 from conf import settings
+from tools.module_manager import ModuleManager
 
 _LOGGER = logging.getLogger(__name__)
 RTE_PCI_TOOL = os.path.join(
     settings.getValue('RTE_SDK'), 'tools', 'dpdk_nic_bind.py')
 
+_DPDK_MODULE_MANAGER = ModuleManager()
+
 #
 # system management
 #
@@ -44,11 +47,9 @@ def init():
         _LOGGER.error('Not running on a compatible Linux version. Exiting...')
         return
 
-    _mount_hugepages()
     _insert_modules()
     _remove_vhost_net()
     _bind_nics()
-    _copy_dpdk_for_guest()
 
 
 def cleanup():
@@ -60,7 +61,6 @@ def cleanup():
 
     _unbind_nics()
     _remove_modules()
-    _umount_hugepages()
     _vhost_user_cleanup()
 
 
@@ -98,79 +98,6 @@ def _is_linux():
     """
     return _platform.startswith('linux') and os.path.isdir('/proc')
 
-#
-# hugepage management
-#
-
-
-def _is_hugepage_available():
-    """Check if hugepages are available on the system.
-    """
-    hugepage_re = re.compile(r'^HugePages_Free:\s+(?P<num_hp>\d+)$')
-
-    # read in meminfo
-    with open('/proc/meminfo') as mem_file:
-        mem_info = mem_file.readlines()
-
-    # first check if module is loaded
-    for line in mem_info:
-        result = hugepage_re.match(line)
-        if not result:
-            continue
-
-        num_huge = result.group('num_hp')
-        if not num_huge:
-            _LOGGER.info('No free hugepages.')
-        else:
-            _LOGGER.info('Found \'%s\' free hugepage(s).', num_huge)
-        return True
-
-    return False
-
-
-def _is_hugepage_mounted():
-    """Check if hugepages are mounted.
-    """
-    output = subprocess.check_output(['mount'], shell=True)
-    my_encoding = locale.getdefaultlocale()[1]
-    for line in output.decode(my_encoding).split('\n'):
-        if 'hugetlbfs' in line:
-            return True
-
-    return False
-
-
-def _mount_hugepages():
-    """Ensure hugepages are mounted.
-    """
-    if not _is_hugepage_available():
-        return
-
-    if _is_hugepage_mounted():
-        return
-
-    if not os.path.exists(settings.getValue('HUGEPAGE_DIR')):
-        os.makedirs(settings.getValue('HUGEPAGE_DIR'))
-    try:
-        tasks.run_task(['sudo', 'mount', '-t', 'hugetlbfs', 'nodev',
-                        settings.getValue('HUGEPAGE_DIR')],
-                       _LOGGER, 'Mounting hugepages...', True)
-    except subprocess.CalledProcessError:
-        _LOGGER.error('Unable to mount hugepages.')
-
-
-def _umount_hugepages():
-    """Ensure hugepages are unmounted.
-    """
-    if not _is_hugepage_mounted():
-        return
-
-    try:
-        tasks.run_task(['sudo', 'umount', settings.getValue('HUGEPAGE_DIR')],
-                       _LOGGER, 'Unmounting hugepages...', True)
-    except subprocess.CalledProcessError:
-        _LOGGER.error('Unable to umount hugepages.')
-
 #
 # module management
 #
@@ -192,16 +119,8 @@ def _is_module_inserted(module):
 def _insert_modules():
     """Ensure required modules are inserted on system.
     """
-    for module in settings.getValue('SYS_MODULES'):
-        if _is_module_inserted(module):
-            continue
 
-        try:
-            tasks.run_task(['sudo', 'modprobe', module], _LOGGER,
-                           'Inserting module \'%s\'...' % module, True)
-        except subprocess.CalledProcessError:
-            _LOGGER.error('Unable to insert module \'%s\'.', module)
-            raise  # fail catastrophically
+    _DPDK_MODULE_MANAGER.insert_modules(settings.getValue('SYS_MODULES'))
 
     mod_path_prefix = settings.getValue('OVS_DIR')
     _insert_module_group('OVS_MODULES', mod_path_prefix)
@@ -237,18 +156,7 @@ def _remove_modules():
     _remove_module_group('OVS_MODULES')
     _remove_module_group('DPDK_MODULES')
 
-    for module in settings.getValue('SYS_MODULES'):
-        # first check if module is loaded
-        if not _is_module_inserted(module):
-            continue
-
-        try:
-            tasks.run_task(['sudo', 'rmmod', module], _LOGGER,
-                           'Removing module \'%s\'...' % module, True)
-        except subprocess.CalledProcessError:
-            _LOGGER.error('Unable to remove module \'%s\'.', module)
-            continue
-
+    _DPDK_MODULE_MANAGER.remove_modules()
 
 def _remove_module_group(module_group):
     """Ensure all modules in a group are removed from the system.
@@ -295,7 +203,7 @@ def _remove_vhost_net():
 
 
 def _bind_nics():
-    """Bind NICs using the Intel DPDK ``pci_unbind.py`` tool.
+    """Bind NICs using the Intel DPDK ``dpdk_nic_bind.py`` tool.
     """
     try:
         tasks.run_task(['sudo', RTE_PCI_TOOL, '--bind', 'igb_uio'] +
@@ -307,10 +215,23 @@ def _bind_nics():
         _LOGGER.error('Unable to bind NICs %s',
                       str(settings.getValue('WHITELIST_NICS')))
 
+def _unbind_nics_get_driver():
+    """Check what driver the NICs should be bound to
+       after unbinding them from DPDK.
+    """
+    _driver_list = []
+    _output = subprocess.check_output([os.path.expanduser(RTE_PCI_TOOL), '--status'])
+    _my_encoding = locale.getdefaultlocale()[1]
+    for line in _output.decode(_my_encoding).split('\n'):
+        for nic in settings.getValue('WHITELIST_NICS'):
+            if nic in line:
+                _driver_list.append((line.split("unused=", 1)[1]))
+    return _driver_list
 
 def _unbind_nics():
-    """Unbind NICs using the Intel DPDK ``pci_unbind.py`` tool.
+    """Unbind NICs using the Intel DPDK ``dpdk_nic_bind.py`` tool.
     """
+    nic_drivers = _unbind_nics_get_driver()
     try:
         tasks.run_task(['sudo', RTE_PCI_TOOL, '--unbind'] +
                        settings.getValue('WHITELIST_NICS'), _LOGGER,
@@ -320,27 +241,22 @@ def _unbind_nics():
     except subprocess.CalledProcessError:
         _LOGGER.error('Unable to unbind NICs %s',
                       str(settings.getValue('WHITELIST_NICS')))
+    # Rebind NICs to their original drivers
+    # using the Intel DPDK ``dpdk_nic_bind.py`` tool.
+    for i, nic in enumerate(settings.getValue('WHITELIST_NICS')):
+        try:
+            if nic_drivers[i] != '':
+                tasks.run_task(['sudo', RTE_PCI_TOOL, '--bind',
+                                nic_drivers[i], nic],
+                               _LOGGER, 'Binding NIC %s...' %
+                               nic,
+                               True)
+        except subprocess.CalledProcessError:
+            _LOGGER.error('Unable to bind NICs %s to drivers %s',
+                          str(settings.getValue('WHITELIST_NICS')),
+                          nic_drivers)
 
 
-def _copy_dpdk_for_guest():
-    """Copy dpdk code to GUEST_SHARE_DIR for use by guests.
-    """
-    guest_share_dir = os.path.join(
-        settings.getValue('GUEST_SHARE_DIR'), 'DPDK')
-
-    if not os.path.exists(guest_share_dir):
-        os.makedirs(guest_share_dir)
-
-    try:
-        tasks.run_task(['rsync', '-a', '-r', '-l', r'--exclude="\.git"',
-                        os.path.join(settings.getValue('RTE_SDK'), ''),
-                        guest_share_dir],
-                       _LOGGER,
-                       'Copying DPDK to shared directory...',
-                       True)
-    except subprocess.CalledProcessError:
-        _LOGGER.error('Unable to copy DPDK to shared directory')
-
 
 #
 # Vhost-user cleanup