Skip to content

Controller

Crane Chu edited this page May 11, 2020 · 8 revisions

我们先来看一下Controller类。这个类提供了对NVMe协议中第3章和第5章内容的支持,分别是访问BAR空间中的NVMe寄存器,以及发送和回收Admin命令。Controller类的完整文档在这里

在这个例子里面,我们测试了Sanitize操作。

import time
import pytest  #L2
import logging

import nvme as d  #L5


def test_sanitize_operations_basic(nvme0, nvme0n1):  #L8
    if nvme0.id_data(331, 328) == 0:  #L9
        pytest.skip("sanitize operation is not supported")  #L10

    logging.info("supported sanitize operation: %d" % nvme0.id_data(331, 328))
    nvme0.sanitize().waitdone()  #L13

    # check sanitize status in log page
    buf = d.Buffer(4096)  #L16
    with pytest.warns(UserWarning, match="AER notification is triggered"):
        nvme0.getlogpage(0x81, buf, 20).waitdone()  #L18
        while buf.data(3, 2) & 0x7 != 1:  #L19
            time.sleep(1)
            nvme0.getlogpage(0x81, buf, 20).waitdone()  #L21
            progress = buf.data(1, 0)*100//0xffff
            logging.info("%d%%" % progress)
  • L2. 引入python模块:time, pytest, logging。我们尽可能使用Python社区现成的成熟的模块,特别是其中的pytest模块。在运行pytest时,pytest会把这个Python文件作为一个测试文件,执行里面所有的测试项目。
  • L5. 引入pynvme模块。
  • L8. 定义了一个标准的Python函数。函数名以test_开头,这样pytest在运行时,会把这个函数作为一个测试项目。pytest会把函数的参数作为一个fixture,实现测试对象的初始化和回收。这里我们声明名字nvme0,pytest在conftest.py文件里面会找到nvme0的定义。fixture替代了传统测试框架的初始化和回收的过程,更加灵活。具体可以参考pytest文档
  • L9. 提取controller identify data的字段328-331字节,看是否支持sanitize操作。
  • L10. 如果不支持sanitize,跳过这个测试项目。
  • L13. 发起sanitize操作。发出的sanitize命令会立刻返回,但sanitize操作是后台操作,需要通过getlogpage检查状态。
  • L16. 创建一个大小为4096字节的Buffer对象buf。Buffer的内存是物理连续的,所以可以作为NVMe命令的DMA空间。pynvme底层驱动会自动为Buffer生成PRP,填充到命令里面。
  • L18. 发送getlogpage admin命令获取Sanitize Status,并等待命令结束。
  • L19. 检查sanitize status,如果没有结束则进入循环。
  • L21. 获取Sanitize Status的logpage数据,提取字段Sanitize Progress,并输出到log。

我们的测试脚本通过pytest来运行,可以指定测试文件和函数的名字,在pciaddr参数中提供待测设备的BDF地址。具体命令行和输出如下。

laptop:~/pynvme▶ sudo python3 -m pytest scripts/cookbook.py::test_sanitize_operations_basic --pciaddr=3d:00.0
================================= test session starts =================================
platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: /home/cranechu/pynvme, inifile: pytest.ini
plugins: cov-2.8.1
collected 1 item                                                                      

scripts/cookbook.py::test_sanitize_operations_basic 
----------------------------------- live log setup ------------------------------------
[2020-05-11 00:29:49.726] INFO pciaddr(55): running tests on DUT 3d:00.0
[2020-05-11 00:29:49.742] INFO script(68): setup random seed: 0xbd408ea2
------------------------------------ live log call ------------------------------------
[2020-05-11 00:29:50.075] INFO test_sanitize_operations_basic(12): supported sanitize operation: 2
[2020-05-11 00:29:51.084] INFO test_sanitize_operations_basic(23): 1%
[2020-05-11 00:29:52.086] INFO test_sanitize_operations_basic(23): 3%
[2020-05-11 00:29:53.089] INFO test_sanitize_operations_basic(23): 5%
[2020-05-11 00:29:54.091] INFO test_sanitize_operations_basic(23): 7%
[2020-05-11 00:29:55.093] INFO test_sanitize_operations_basic(23): 9%
[2020-05-11 00:29:56.094] WARNING test_sanitize_operations_basic(21): AER triggered, dword0: 0x810106
[2020-05-11 00:29:56.094] INFO test_sanitize_operations_basic(23): 100%
PASSED                                                                          [100%]
---------------------------------- live log teardown ----------------------------------
[2020-05-11 00:29:56.096] INFO script(70): test duration: 6.354 sec


================================== 1 passed in 6.40s ==================================

请留意在运行pynvme测试之前,需要通过make setup来建立pynvme的运行时环境。重复执行多次make setup并不会有副作用。下面这个make setup最终在3d:00.0这个PCIe SSD设备上建立了pynvme/SPDK的运行时环境(内核切换到UIO驱动)。

laptop:~/pynvme▶ make setup
sudo rm -rf /run/dpdk
sudo ./spdk/scripts/setup.sh cleanup
Clean
sudo ./spdk/scripts/setup.sh reset
0000:3a:00.0 (14a4 5100): Already using the nvme driver
0000:3d:00.0 (14a4 2f00): Already using the nvme driver
sudo rm -f /var/tmp/spdk.sock*
sudo rm -f /var/tmp/pynvme.sock*
sudo rm -rf .pytest_cache
sudo fuser -k 4420/tcp
make: [Makefile:72: reset] Error 1 (ignored)
sudo sh -c 'find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf'
xhost +local:		# enable GUI with root/sudo
non-network local connections being added to access control list
sudo chmod 777 /tmp
sudo sh -c 'find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf'
sed -i 's/XXXX:BB:DD.F/0000:3a:00.0/g' .vscode/settings.json
sudo HUGEMEM=4850 DRIVER_OVERRIDE=uio_pci_generic ./spdk/scripts/setup.sh  	# UIO is recommended
0000:3a:00.0 (14a4 5100): Active mountpoints on /dev/nvme0n1, so not binding PCI dev
0000:3d:00.0 (14a4 2f00): nvme -> uio_pci_generic

Clone this wiki locally