-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding API and tests for IOCTL requests (and bypassing casadm)
Signed-off-by: Karolina Rogowska <karolina.rogowska@intel.com>
- Loading branch information
1 parent
5afc8af
commit 6bcd126
Showing
9 changed files
with
592 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# | ||
# Copyright(c) 2021 Intel Corporation | ||
# SPDX-License-Identifier: BSD-3-Clause-Clear | ||
# | ||
|
||
from api.cas.ioctl.cas_structs import * | ||
from api.cas.ioctl.ioctl import IOWR | ||
|
||
|
||
class IORequest: | ||
def __init__(self, | ||
command_number: RequestCode, | ||
command_direction=None): | ||
self.command_number = command_number.value | ||
self.command_struct = self.get_struct() | ||
self.command = command_direction(self.command_number, self.command_struct) | ||
|
||
def get_struct(self): | ||
pass | ||
|
||
|
||
class StartCacheRequest(IORequest): | ||
def __init__(self, | ||
cache_path_name: str, | ||
cache_id: int = 1, | ||
init_cache: InitCache = InitCache.CACHE_INIT_NEW, | ||
caching_mode: CacheMode = CacheMode.default, | ||
line_size: CacheLineSize = CacheLineSize.default, | ||
force: int = 1): | ||
self.cache_id = ctypes.c_uint16(cache_id).value | ||
self.init_cache = init_cache.value | ||
self.cache_path_name = ctypes.create_string_buffer( | ||
bytes(cache_path_name, encoding='ascii'), MAX_STR_LEN).value | ||
self.caching_mode = caching_mode.value | ||
self.line_size = line_size.value | ||
self.force = ctypes.c_uint8(force).value | ||
super().__init__(RequestCode.START_CACHE_CODE, IOWR) | ||
|
||
def get_struct(self): | ||
return StartCacheStructure( | ||
cache_id=self.cache_id, | ||
init_cache=self.init_cache, | ||
cache_path_name=self.cache_path_name, | ||
caching_mode=self.caching_mode, | ||
line_size=self.line_size, | ||
force=self.force | ||
) | ||
|
||
def __repr__(self): | ||
return f'{self.command_struct}' | ||
|
||
|
||
class StopCacheRequest(IORequest): | ||
def __init__(self, | ||
cache_id: int = 1, | ||
flush_data: int = 1): | ||
self.cache_id = ctypes.c_uint16(cache_id).value | ||
self.flush_data = ctypes.c_uint8(flush_data).value | ||
super().__init__(RequestCode.STOP_CACHE_CODE, IOWR) | ||
|
||
def get_struct(self): | ||
return StopCacheStructure( | ||
cache_id=self.cache_id, | ||
flush_data=self.flush_data | ||
) | ||
|
||
def __repr__(self): | ||
return f'{self.command_struct}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# | ||
# Copyright(c) 2021 Intel Corporation | ||
# SPDX-License-Identifier: BSD-3-Clause-Clear | ||
# | ||
|
||
import ctypes | ||
from enum import Enum | ||
|
||
|
||
class RequestCode(Enum): | ||
START_CACHE_CODE = ctypes.c_uint(21).value | ||
STOP_CACHE_CODE = ctypes.c_uint(2).value | ||
SET_CACHE_STATE_CODE = ctypes.c_uint(3).value | ||
INSERT_CORE_CODE = ctypes.c_uint(22).value | ||
REMOVE_CORE_CODE = ctypes.c_uint(23).value | ||
RESET_STATS_CODE = ctypes.c_uint(6).value | ||
FLUSH_CACHE_CODE = ctypes.c_uint(9).value | ||
INTERRUPT_FLUSHING_CODE = ctypes.c_uint(10).value | ||
FLUSH_CORE_CODE = ctypes.c_uint(11).value | ||
CACHE_INFO_CODE = ctypes.c_uint(24).value | ||
CORE_INFO_CODE = ctypes.c_uint(25).value | ||
PARTITION_INFO_CODE = ctypes.c_uint(14).value | ||
PARTITION_SET_CODE = ctypes.c_uint(15).value | ||
GET_CACHE_COUNT_CODE = ctypes.c_uint(16).value | ||
LIST_CACHE_CODE = ctypes.c_uint(17).value | ||
UPGRADE_CODE = ctypes.c_uint(19).value | ||
GET_CORE_POOL_COUNT_CODE = ctypes.c_uint(26).value | ||
GET_CORE_POOL_PATHS_CODE = ctypes.c_uint(27).value | ||
CORE_POOL_REMOVE_CODE = ctypes.c_uint(28).value | ||
CACHE_CHECK_DEVICE_CODE = ctypes.c_uint(29).value | ||
SET_CORE_PARAM_CODE = ctypes.c_uint(30).value | ||
GET_CORE_PARAM_CODE = ctypes.c_uint(31).value | ||
SET_CACHE_PARAM_CODE = ctypes.c_uint(32).value | ||
GET_CACHE_PARAM_CODE = ctypes.c_uint(33).value | ||
GET_STATS_CODE = ctypes.c_uint(34).value | ||
PURGE_CACHE_CODE = ctypes.c_uint(35).value | ||
PURGE_CORE_CODE = ctypes.c_uint(36).value | ||
|
||
|
||
KiB = ctypes.c_ulonglong(1024).value | ||
MAX_STR_LEN = 4096 | ||
MAX_ELEVATOR_NAME = 16 | ||
|
||
|
||
class InitCache(Enum): | ||
CACHE_INIT_NEW = ctypes.c_uint8(0).value | ||
CACHE_INIT_LOAD = ctypes.c_uint8(1).value | ||
|
||
|
||
class CacheMode(Enum): | ||
ocf_cache_mode_wt = ctypes.c_int(0).value | ||
ocf_cache_mode_wb = ctypes.c_int(1).value | ||
ocf_cache_mode_wa = ctypes.c_int(2).value | ||
ocf_cache_mode_pt = ctypes.c_int(3).value | ||
ocf_cache_mode_wi = ctypes.c_int(4).value | ||
ocf_cache_mode_wo = ctypes.c_int(5).value | ||
default = ocf_cache_mode_wt | ||
|
||
|
||
class CacheLineSize(Enum): | ||
ocf_cache_line_size_4 = ctypes.c_ulonglong(4).value * KiB | ||
ocf_cache_line_size_8 = ctypes.c_ulonglong(8).value * KiB | ||
ocf_cache_line_size16 = ctypes.c_ulonglong(16).value * KiB | ||
ocf_cache_line_size_32 = ctypes.c_ulonglong(32).value * KiB | ||
ocf_cache_line_size_64 = ctypes.c_ulonglong(64).value * KiB | ||
default = ocf_cache_line_size_4 | ||
|
||
|
||
class StartCacheStructure(ctypes.Structure): | ||
_fields_ = [ | ||
('cache_id', ctypes.c_uint16), | ||
('init_cache', ctypes.c_uint8), | ||
('cache_path_name', ctypes.c_char * MAX_STR_LEN), | ||
('caching_mode', ctypes.c_int), | ||
('flush_data', ctypes.c_uint8), | ||
('line_size', ctypes.c_ulonglong), | ||
('force', ctypes.c_uint8), | ||
('min_free_ram', ctypes.c_uint64), | ||
('metadata_mode_optimal', ctypes.c_uint8), | ||
('cache_elevator', ctypes.c_char * MAX_ELEVATOR_NAME), | ||
('ext_err_code', ctypes.c_int) | ||
] | ||
|
||
def __repr__(self): | ||
return (f'cache_id: {self.cache_id}\n' | ||
f'init_cache: {self.init_cache}\n' | ||
f'cache_path_name: {self.cache_path_name}\n' | ||
f'caching_mode: {self.caching_mode}\n' | ||
f'flush_data: {self.flush_data}\n' | ||
f'line_size: {self.line_size}\n' | ||
f'force: {self.force}\n' | ||
f'min_free_ram: {self.min_free_ram}\n' | ||
f'metadata_mode_optimal: {self.metadata_mode_optimal}\n' | ||
f'cache_elevator: {self.cache_elevator}\n' | ||
f'ext_err_code: {self.ext_err_code}\n') | ||
|
||
|
||
class StopCacheStructure(ctypes.Structure): | ||
_fields_ = [ | ||
('cache_id', ctypes.c_uint16), | ||
('flush_data', ctypes.c_uint8), | ||
('ext_err_code', ctypes.c_int) | ||
] | ||
|
||
def __repr__(self): | ||
return (f'cache_id: {self.cache_id}\n' | ||
f'flush_data: {self.flush_data}\n' | ||
f'ext_err_code: {self.ext_err_code}\n') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# | ||
# Copyright(c) 2021 Intel Corporation | ||
# SPDX-License-Identifier: BSD-3-Clause-Clear | ||
# | ||
|
||
import ctypes | ||
import marshal | ||
import os | ||
from time import sleep | ||
|
||
from core.test_run import TestRun | ||
from test_tools.fs_utils import chmod_numerical, remove, check_if_directory_exists, \ | ||
create_directory | ||
|
||
IOC_NRBITS = 8 | ||
IOC_TYPEBITS = 8 | ||
IOC_SIZEBITS = 14 | ||
IOC_DIRBITS = 2 | ||
|
||
IOC_NRMASK = (1 << IOC_NRBITS) - 1 # 255 | ||
IOC_TYPEMASK = (1 << IOC_TYPEBITS) - 1 # 255 | ||
IOC_SIZEMASK = (1 << IOC_SIZEBITS) - 1 # 16 383 | ||
IOC_DIRMASK = (1 << IOC_DIRBITS) - 1 # 3 | ||
|
||
IOC_NRSHIFT = 0 # 0 | ||
IOC_TYPESHIFT = IOC_NRSHIFT + IOC_NRBITS # 8 | ||
IOC_SIZESHIFT = IOC_TYPESHIFT + IOC_TYPEBITS # 16 | ||
IOC_DIRSHIFT = IOC_SIZESHIFT + IOC_SIZEBITS # 30 | ||
|
||
IOC_NONE = 0 | ||
IOC_WRITE = 1 | ||
IOC_READ = 2 | ||
|
||
KCAS_IOCTL_MAGIC = 0xBA # 186 | ||
|
||
IOC_IN = IOC_WRITE << IOC_DIRSHIFT # 1 073 741 824 | ||
IOC_OUT = IOC_READ << IOC_DIRSHIFT # 2 147 483 648 | ||
IOC_INOUT = (IOC_WRITE | IOC_READ) << IOC_DIRSHIFT # 3 221 225 472 | ||
IOCSIZE_MASK = IOC_SIZEMASK << IOC_SIZESHIFT # 1 073 676 288 | ||
IOCSIZE_SHIFT = IOC_SIZESHIFT # 16 | ||
|
||
|
||
def IOC(dir, type, nr, size): | ||
if dir > IOC_DIRMASK: | ||
raise OverflowError(f"IO direction value {dir} exceeds {IOC_DIRMASK}") | ||
dir <<= IOC_DIRSHIFT | ||
|
||
if type > IOC_TYPEMASK: | ||
raise OverflowError(f"IO type value {type} exceeds {IOC_TYPEMASK}") | ||
type <<= IOC_TYPESHIFT | ||
|
||
if nr > IOC_NRMASK: | ||
raise OverflowError(f"IO command value {nr} exceeds {IOC_NRMASK}") | ||
nr <<= IOC_NRSHIFT | ||
|
||
if size > IOC_SIZEMASK: | ||
raise OverflowError(f"IO size value {size} exceeds {IOC_SIZEMASK}") | ||
size <<= IOC_SIZESHIFT | ||
|
||
return dir | type | nr | size | ||
|
||
|
||
def IOC_TYPECHECK(item): | ||
return ctypes.sizeof(item) | ||
|
||
|
||
def IO(nr): | ||
return IOC(IOC_NONE, KCAS_IOCTL_MAGIC, nr, 0) | ||
|
||
|
||
def IOR(nr, size): | ||
return IOC(IOC_READ, KCAS_IOCTL_MAGIC, nr, IOC_TYPECHECK(size)) | ||
|
||
|
||
def IOW(nr, size): | ||
return IOC(IOC_WRITE, KCAS_IOCTL_MAGIC, nr, IOC_TYPECHECK(size)) | ||
|
||
|
||
def IOWR(nr, size): | ||
return IOC(IOC_READ | IOC_WRITE, KCAS_IOCTL_MAGIC, nr, IOC_TYPECHECK(size)) | ||
|
||
|
||
def IOR_BAD(nr, size): | ||
return IOC(IOC_READ, KCAS_IOCTL_MAGIC, nr, ctypes.sizeof(size)) | ||
|
||
|
||
def IOW_BAD(nr, size): | ||
return IOC(IOC_WRITE, KCAS_IOCTL_MAGIC, nr, ctypes.sizeof(size)) | ||
|
||
|
||
def IOWR_BAD(nr, size): | ||
return IOC(IOC_READ | IOC_WRITE, KCAS_IOCTL_MAGIC, nr, ctypes.sizeof(size)) | ||
|
||
|
||
def IOC_DIR(nr): | ||
return (nr >> IOC_DIRSHIFT) & IOC_DIRMASK | ||
|
||
|
||
def IOC_TYPE(nr): | ||
return (nr >> IOC_TYPESHIFT) & IOC_TYPEMASK | ||
|
||
|
||
def IOC_NR(nr): | ||
return (nr >> IOC_NRSHIFT) & IOC_NRMASK | ||
|
||
|
||
def IOC_SIZE(nr): | ||
return (nr >> IOC_SIZESHIFT) & IOC_SIZEMASK | ||
|
||
|
||
temp_dir = '/tmp/cas' | ||
struct_path = os.path.join(temp_dir, 'dump_file') | ||
script_source = os.path.join(f'{os.path.dirname(__file__)}', 'send_ioctl_script.py') | ||
script_dest = os.path.join(temp_dir, 'send_ioctl_script.py') | ||
|
||
|
||
def send_script_with_dumped_args(): | ||
if not check_if_directory_exists(temp_dir): | ||
create_directory(temp_dir, True) | ||
|
||
TestRun.executor.rsync_to(script_source, script_dest) | ||
chmod_numerical(script_dest, 550) | ||
|
||
TestRun.executor.rsync_to(struct_path, struct_path) | ||
chmod_numerical(struct_path, 440) | ||
|
||
|
||
def cas_ioctl(cas_ioctl_request, interrupt: bool = False): | ||
if not os.path.exists(temp_dir): | ||
os.mkdir(temp_dir) | ||
|
||
with open(struct_path, 'wb') as dump_file: | ||
marshal.dump(cas_ioctl_request.command_struct, dump_file) | ||
|
||
send_script_with_dumped_args() | ||
if interrupt: | ||
pid = TestRun.executor.run_in_background( | ||
f"{script_dest} -c {cas_ioctl_request.command} -s {struct_path}" | ||
) | ||
sleep(2) | ||
TestRun.executor.kill_process(pid) | ||
else: | ||
TestRun.executor.run(f"{script_dest} -c {cas_ioctl_request.command} -s {struct_path}") | ||
if check_if_directory_exists(temp_dir): | ||
remove(temp_dir, True, True, True) | ||
if os.path.exists(struct_path): | ||
os.remove(struct_path) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# Copyright(c) 2021 Intel Corporation | ||
# SPDX-License-Identifier: BSD-3-Clause-Clear | ||
# | ||
|
||
import argparse | ||
import marshal | ||
import os | ||
import sys | ||
from fcntl import ioctl | ||
|
||
|
||
def main(): | ||
CAS_DEVICE = '/dev/cas_ctrl' | ||
|
||
parser = argparse.ArgumentParser(description=f'Send ioctl request to {CAS_DEVICE}') | ||
|
||
parser.add_argument('-c', '--command', action='store', dest='command', type=str, | ||
required=True, help=f"Specific request code to send to {CAS_DEVICE}") | ||
parser.add_argument('-s', '--struct', action='store', dest='struct', type=str, | ||
required=True, help="Structure of CAS request") | ||
args = parser.parse_args() | ||
|
||
with open(args.struct, 'rb') as struct_file: | ||
struct = bytearray(marshal.load(struct_file)) | ||
|
||
fd = os.open(CAS_DEVICE, os.O_RDWR) | ||
try: | ||
ioctl(fd, int(args.command), struct) | ||
except OSError as err: | ||
print(f"IOCTL request returned error: {err}", sys.stdout) | ||
finally: | ||
os.close(fd) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# | ||
# Copyright(c) 2021 Intel Corporation | ||
# SPDX-License-Identifier: BSD-3-Clause-Clear | ||
# | ||
|
||
from api.cas.cli_messages import __check_string_msg | ||
from core.test_run import TestRun | ||
|
||
|
||
interrupt_stop = [ | ||
r"Waiting for cache stop interrupted\. Stop will finish asynchronously\." | ||
] | ||
|
||
interrupt_start = [ | ||
r"Cache added successfully, but waiting interrupted\. Rollback" | ||
] | ||
|
||
load_and_force = [ | ||
r"cache\d+: Using \'force\' flag is forbidden for load operation\." | ||
] | ||
|
||
|
||
def clear_dmesg(): | ||
TestRun.executor.run_expect_success('dmesg -C') | ||
|
||
|
||
def check_dmesg(searched_phrase: str): | ||
dmesg_out = TestRun.executor.run_expect_success("dmesg").stdout | ||
__check_string_msg(dmesg_out, searched_phrase) |
Oops, something went wrong.