def test_reservered_qpn(self): """ Alloc reserved qpn multiple times and then dealloc the qpns. In addition, the test includes bad flows where a fake qpn gets deallocated, and a real qpn gets deallocated twice. """ try: # Alloc qp number multiple times. qpns = [] for i in range(1000): qpns.append(Mlx5Context.reserved_qpn_alloc(self.ctx)) for i in range(1000): Mlx5Context.reserved_qpn_dealloc(self.ctx, qpns[i]) # Dealloc qp number that was not allocated. qpn = Mlx5Context.reserved_qpn_alloc(self.ctx) with self.assertRaises(PyverbsRDMAError) as ex: fake_qpn = qpn - 1 Mlx5Context.reserved_qpn_dealloc(self.ctx, fake_qpn) self.assertEqual(ex.exception.error_code, errno.EINVAL) # Try to dealloc same qp number twice. Mlx5Context.reserved_qpn_dealloc(self.ctx, qpn) with self.assertRaises(PyverbsRDMAError) as ex: Mlx5Context.reserved_qpn_dealloc(self.ctx, qpn) self.assertEqual(ex.exception.error_code, errno.EINVAL) except PyverbsRDMAError as ex: if ex.error_code == errno.EOPNOTSUPP: raise unittest.SkipTest( 'Alloc reserved QP number is not supported') raise ex
def test_mlx5_dek_management(self): """ Test crypto login and DEK management APIs. The test checks also that invalid actions are not permited, e.g, create DEK not in login session. """ try: self.pd = PD(self.ctx) cred_bytes = struct.pack('!6Q', *self.crypto_details['credential']) key = struct.pack('!5Q', *self.crypto_details['wrapped_key']) self.dek_init_attr = \ Mlx5DEKInitAttr(self.pd, key=key, key_size=dve.MLX5DV_CRYPTO_KEY_SIZE_128, key_purpose=dve.MLX5DV_CRYPTO_KEY_PURPOSE_AES_XTS, opaque=DEK_OPAQUE) self.verify_create_dek_out_of_login_session() self.verify_login_state(dve.MLX5DV_CRYPTO_LOGIN_STATE_NO_LOGIN) # Login to crypto session self.login_attr = Mlx5CryptoLoginAttr(cred_bytes) Mlx5Context.crypto_login(self.ctx, self.login_attr) self.verify_login_state(dve.MLX5DV_CRYPTO_LOGIN_STATE_VALID) self.verify_login_twice() self.dek = Mlx5DEK(self.ctx, self.dek_init_attr) self.verify_dek_opaque() self.dek.close() # Logout from crypto session Mlx5Context.crypto_logout(self.ctx) self.verify_login_state(dve.MLX5DV_CRYPTO_LOGIN_STATE_NO_LOGIN) except PyverbsRDMAError as ex: print(ex) if ex.error_code == errno.EOPNOTSUPP: raise unittest.SkipTest('Create crypto elements is not supported') raise ex
def func_wrapper(instance): try: ctx = Mlx5Context(Mlx5DVContextAttr(), instance.dev_name) except PyverbsUserError as ex: raise unittest.SkipTest(f'Could not open mlx5 context ({ex})') except PyverbsRDMAError: raise unittest.SkipTest('Opening mlx5 context is not supported') # Query NIC Flow Table capabilities cmd_in = struct.pack('!HIH8s', MLX5_CMD_OP_QUERY_HCA_CAP, 0, MLX5_CMD_MOD_NIC_FLOW_TABLE_CAP << 1 | 0x1, bytes(8)) try: cmd_out = Mlx5Context.devx_general_cmd( ctx, cmd_in, MLX5_CMD_OP_QUERY_HCA_CAP_OUT_LEN) except PyverbsRDMAError as ex: if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]: raise unittest.SkipTest( 'DevX general command is not supported') raise ex cmd_view = memoryview(cmd_out) status = cmd_view[0] if status: raise PyverbsRDMAError( 'Query NIC Flow Table CAPs failed with status' f' ({status})') # Verify that both NIC RX and TX support reformat actions by checking # the following PRM fields: encap_general_header, # log_max_packet_reformat, and reformat (for both RX and TX). if not (cmd_view[20] & 0x80 and cmd_view[21] & 0x1f and cmd_view[80] & 0x1 and cmd_view[272] & 0x1): raise unittest.SkipTest('NIC flow table does not support reformat') return func(instance)
def verify_login_twice(self): """ Verify that when there is already a login session alive the second login fails. """ with self.assertRaises(PyverbsRDMAError) as ex: Mlx5Context.crypto_login(self.ctx, self.login_attr) self.assertEqual(ex.exception.error_code, errno.EEXIST)
def create_client_dek(self): """ Create DEK using the client resources. """ cred_bytes = struct.pack('!6Q', *self.crypto_details['credential']) log_attr = Mlx5CryptoLoginAttr(cred_bytes) Mlx5Context.crypto_login(self.client.ctx, log_attr) key = struct.pack('!5Q', *self.crypto_details['wrapped_key']) if self.key_size == dve.MLX5DV_CRYPTO_KEY_SIZE_256: key = struct.pack('!9Q', *self.crypto_details['wrapped_256_bits_key']) self.dek_attr = Mlx5DEKInitAttr(self.client.pd, key=key, key_size=self.key_size, key_purpose=dve.MLX5DV_CRYPTO_KEY_PURPOSE_AES_XTS) self.dek = Mlx5DEK(self.client.ctx, self.dek_attr)
def wrapper(instance): cmd_in = struct.pack('!HIH8s', MLX5_CMD_OP_QUERY_HCA_CAP, 0, MLX5_CMD_MOD_DEVICE_MEMORY_CAP << 1 | 0x1, bytes(8)) cmd_out = Mlx5Context.devx_general_cmd( instance.ctx, cmd_in, MLX5_CMD_OP_QUERY_HCA_CAP_OUT_LEN) cmd_view = memoryview(cmd_out) status = cmd_view[0] if status: raise PyverbsRDMAError( 'Query Device Memory CAPs failed with status' f' ({status})') memic_op_support = int.from_bytes(cmd_view[80:84], 'big') increment_size_sup = cmd_view[20] test_and_set_size_sup = cmd_view[22] # Verify that MEMIC atomic operations (both increment and test_and_set) # are supported with write/read size of 1 Byte. if memic_op_support & 0x3 != 0x3: raise unittest.SkipTest( 'MEMIC atomic operations are not supported') if not increment_size_sup & test_and_set_size_sup & 0x1: raise unittest.SkipTest( 'MEMIC atomic operations are not supported with 1 Bytes read/write sizes' ) return func(instance)
def _create_mr_devx(self, rdma_device, buf_size): """This method create mkey and memory buffer using devx (part of ofed driver). """ mlx5dv_attr = Mlx5DVContextAttr() self.ctx = Mlx5Context(mlx5dv_attr, name=rdma_device) self.my_pd = PD(self.ctx) self.dv_pd = Mlx5DvObj(dve.MLX5DV_OBJ_PD, pd=self.my_pd).dvpd self.umem = self._create_umem(self.ctx, buf_size) self.mkey_ctx = SwMkc(umr_en=0, lr=1, lw=1, access_mode_1_0=0x1, pd=self.dv_pd.pdn, start_addr=self.umem.umem_addr, len=buf_size) mkey_in = CreateMkeyIn(sw_mkc=self.mkey_ctx, mkey_umem_id=self.umem.umem_id, mkey_umem_valid=1) self.mkey_obj = Mlx5DevxObj(self.ctx, mkey_in, len(CreateMkeyOut())) mkey_out = CreateMkeyOut(self.mkey_obj.out_view) if mkey_out.status: raise PyverbsRDMAError( "Failed to create mkey with syndrome {0}".format( mkey_out.syndrome)) mkey_index = mkey_out.mkey_index self.lkey = mkey_index << 8
def create_context(self): mlx5dv_attr = Mlx5DVContextAttr() try: self.ctx = Mlx5Context(mlx5dv_attr, name=self.dev_name) except PyverbsUserError as ex: raise unittest.SkipTest(f'Could not open mlx5 context ({ex})') except PyverbsRDMAError: raise unittest.SkipTest('Opening mlx5 context is not supported')
def create_context(self): try: attr = Mlx5DVContextAttr(dve.MLX5DV_CONTEXT_FLAGS_DEVX) self.ctx = Mlx5Context(attr, self.dev_name) except PyverbsUserError as ex: raise unittest.SkipTest(f'Could not open mlx5 context ({ex})') except PyverbsRDMAError: raise unittest.SkipTest('Opening mlx5 DevX context is not supported')
def __init__(self, dev_name): try: mlx5dv_attr = Mlx5DVContextAttr(e.MLX5DV_CONTEXT_FLAGS_DEVX) self.ctx = Mlx5Context(mlx5dv_attr, dev_name) except PyverbsUserError as ex: raise unittest.SkipTest('Could not open mlx5 context ({})'.format( str(ex))) except PyverbsRDMAError: raise unittest.SkipTest( 'Opening mlx5 DevX context is not supported') self.pps = []
def create_context(self): mlx5dv_attr = Mlx5DVContextAttr() try: self.ctx = Mlx5Context(mlx5dv_attr, name=self.dev_name) except PyverbsUserError as ex: raise unittest.SkipTest(f'Could not open mlx5 context ({ex})') except PyverbsRDMAError: raise unittest.SkipTest('Opening mlx5 context is not supported') if self.requested_dev_cap: if not self.ctx.query_mlx5_device().flags & self.requested_dev_cap: miss_caps = context_flags_to_str(self.requested_dev_cap) raise unittest.SkipTest(f'Device caps doesn\'t support {miss_caps}')
def check_crypto_caps(dev_name): """ Check that this device support crypto actions. :param dev_name: The device name. """ mlx5dv_attr = Mlx5DVContextAttr() ctx = Mlx5Context(mlx5dv_attr, name=dev_name) crypto_caps = ctx.query_mlx5_device().crypto_caps failed_selftests = crypto_caps['failed_selftests'] if failed_selftests: raise unittest.SkipTest(f'The device crypto selftest failed ({failed_selftests})') if not dve.MLX5DV_CRYPTO_ENGINES_CAP_AES_XTS & crypto_caps['crypto_engines']: raise unittest.SkipTest('The device crypto engines does not support AES')
def func_wrapper(instance): try: ctx = Mlx5Context(Mlx5DVContextAttr(), instance.dev_name) except PyverbsUserError as ex: raise unittest.SkipTest(f'Could not open mlx5 context ({ex})') except PyverbsRDMAError: raise unittest.SkipTest('Opening mlx5 context is not supported') # Query NIC Flow Table capabilities cmd_in = struct.pack('!HIH8s', MLX5_CMD_OP_QUERY_HCA_CAP, 0, MLX5_CMD_MOD_NIC_FLOW_TABLE_CAP << 1 | 0x1, bytes(8)) cmd_out = Mlx5Context.devx_general_cmd( ctx, cmd_in, MLX5_CMD_OP_QUERY_HCA_CAP_OUT_LEN) cmd_view = memoryview(cmd_out) status = cmd_view[0] if status: raise PyverbsRDMAError( 'Query NIC Flow Table CAPs failed with status' f' ({status})') # Verify that both NIC RX and TX support reformat actions if not (cmd_view[80] & 0x1 and cmd_view[272] & 0x1): raise unittest.SkipTest('NIC flow table does not support reformat') return func(instance)
def create_conn_param(self, qp_num=0, conn_idx=0): if conn_idx and self.passive: try: ctx = self.child_id.context self.reserved_qp_num = Mlx5Context.reserved_qpn_alloc(ctx) except PyverbsRDMAError as ex: if ex.error_code == errno.EOPNOTSUPP: raise unittest.SkipTest( 'Alloc reserved QP number is not supported') raise ex qp_num = self.reserved_qp_num else: qp_num = self.qps[conn_idx].qp_num return ConnParam(qp_num=qp_num)
def convert_ts_to_ns(ctx, device_ts): """ Convert device timestamp from HCA core clock units to corresponding nanosecond counts. :param ctx: The context that gets this timestamp. :param device_ts: The device timestamp to translate. :return: Timestamp in nanoseconds """ try: timestamp_in_ns = Mlx5Context.device_timestamp_to_ns(ctx, device_ts) except PyverbsRDMAError as ex: if ex.error_code == errno.EOPNOTSUPP: raise unittest.SkipTest('Converting timestamp to nanoseconds is not supported') raise ex return timestamp_in_ns
def test_dma_memcpy_large_data_bad_flow(self): """ Bad flow test, testing DMA memcpy with data larger than the maximum allowed size, according to the HCA capabilities. :return: None """ try: ctx = Mlx5Context(Mlx5DVContextAttr(), name=self.dev_name) except PyverbsUserError as ex: raise unittest.SkipTest(f'Could not open mlx5 context ({ex})') except PyverbsRDMAError: raise unittest.SkipTest('Opening mlx5 context is not supported') max_size = ctx.query_mlx5_device( dve.MLX5DV_CONTEXT_MASK_WR_MEMCPY_LENGTH).max_wr_memcpy_length max_size = max_size if max_size else 1024 with self.assertRaises(PyverbsRDMAError): self.dma_memcpy(max_size + 1)
def test_dv_query_port(self): """ Test the DV query port and that no error is returned. """ for port in range(1, self.attr_ex.phys_port_cnt_ex + 1): try: port_attr = Mlx5Context.query_mlx5_port(self.ctx, port) except PyverbsRDMAError as ex: if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]: raise unittest.SkipTest( f'mlx5dv_query_port() isn\'t supported') raise ex if (port_attr.flags & e.MLX5DV_QUERY_PORT_VPORT_STEERING_ICM_RX_): self.assertNotEqual(port_attr.vport_steering_icm_rx, 0, f'Vport steering icm rx address is zero') if (port_attr.flags & e.MLX5DV_QUERY_PORT_VPORT_STEERING_ICM_TX_): self.assertNotEqual(port_attr.vport_steering_icm_tx, 0, f'Vport steering icm tx address is zero') if (port_attr.flags & e.MLX5DV_QUERY_PORT_VPORT_REG_C0_): self.assertNotEqual(port_attr.reg_c0_mask, 0, f'Vport reg c0 mask is zero')
def disconnect(self): if self.cm_res.reserved_qp_num and self.cm_res.passive: Mlx5Context.reserved_qpn_dealloc(self.cm_res.child_id.context, self.cm_res.reserved_qp_num) self.cm_res.reserved_qp_num = 0 super().disconnect()
def verify_login_state(self, expected_state): """ Query the session login state and verify that it's as expected. """ state = Mlx5Context.query_login_state(self.ctx) self.assertEqual(state, expected_state)