示例#1
0
文件: utils.py 项目: Edan7/rdma-core
def poll_cq(cq, count=1, data=None):
    """
    Poll <count> completions from the CQ.
    Note: This function calls the blocking poll() method of the CQ
    until <count> completions were received. Alternatively, gets a
    single CQ event when events are used.
    :param cq: CQ to poll from
    :param count: How many completions to poll
    :param data: In case of a work request with immediate, the immediate data
                 to be compared after poll
    :return: An array of work completions of length <count>, None
             when events are used
    """
    wcs = []
    channel = cq.comp_channel
    while count > 0:
        if channel:
            channel.get_cq_event(cq)
            cq.req_notify()
        nc, tmp_wcs = cq.poll(count)
        for wc in tmp_wcs:
            if wc.status != e.IBV_WC_SUCCESS:
                raise PyverbsRDMAError(
                    'Completion status is {s}'.format(
                        s=wc_status_to_str(wc.status)), wc.status)
            if data:
                if wc.wc_flags & e.IBV_WC_WITH_IMM == 0:
                    raise PyverbsRDMAError('Completion without immediate')
                assert socket.ntohl(wc.imm_data) == data
        count -= nc
        wcs.extend(tmp_wcs)
    return wcs
    def poll_cq_ex_ts(cqex, ts_type=None):
        """
        Poll completion from the extended CQ.
        :param cqex: CQEX to poll from
        :param ts_type: If set, read the CQE timestamp in this format
        :return: The CQE timestamp if it requested.
        """
        polling_timeout = 10
        start = datetime.datetime.now()
        ts = 0

        poll_attr = PollCqAttr()
        ret = cqex.start_poll(poll_attr)
        while ret == 2 and (datetime.datetime.now() - start).seconds < polling_timeout:
            ret = cqex.start_poll(poll_attr)
        if ret == 2:
            raise PyverbsRDMAError('Failed to poll CQEX - Got timeout')
        if ret != 0:
            raise PyverbsRDMAError('Failed to poll CQEX')
        if cqex.status != e.IBV_WC_SUCCESS:
            raise PyverbsRDMAError('Completion status is {cqex.status}')
        if ts_type == FREE_RUNNING:
            ts = cqex.read_timestamp()
        if ts_type == REAL_TIME:
            ts = cqex.read_completion_wallclock_ns()
        cqex.end_poll()
        return ts
示例#3
0
    def test_query_gid_ex_bad_flow(self):
        """
        Test ibv_query_gid_ex() with an empty index
        """
        ctx, device_attr, _ = self.devices[0]
        try:
            port_attr = ctx.query_port(1)
            max_entries = device_attr.phys_port_cnt * port_attr.gid_tbl_len
            gid_indices = {
                gid_entry.gid_index
                for gid_entry in ctx.query_gid_table(max_entries)
                if gid_entry.port_num == 1
            }

            possible_indices = set(range(port_attr.gid_tbl_len))
            try:
                no_gid_index = possible_indices.difference(gid_indices).pop()
            except KeyError:
                # all indices are populated by GIDs
                raise unittest.SkipTest('All gid indices populated,'
                                        ' cannot check bad flow')

            ctx.query_gid_ex(port_num=1, gid_index=no_gid_index)
        except PyverbsRDMAError as ex:
            if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]:
                raise unittest.SkipTest('ibv_query_gid_ex is not'
                                        ' supported on this device')
            self.assertEqual(
                ex.error_code, errno.ENODATA,
                f'Got {os.strerror(ex.error_code)} but '
                f'Expected {os.strerror(errno.ENODATA)}')
        else:
            raise PyverbsRDMAError(f'Successfully queried '
                                   'non-existent gid index {i}')
 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)
示例#5
0
 def test_dmabuf_reg_mr_bad_flags(self):
     """
     Verify that illegal flags combination fails as expected
     """
     check_dmabuf_support(self.gpu)
     for ctx, attr, attr_ex in self.devices:
         with PD(ctx) as pd:
             check_dmabuf_mr_support(pd, self.gpu)
             for i in range(5):
                 flags = random.sample([
                     e.IBV_ACCESS_REMOTE_WRITE, e.IBV_ACCESS_REMOTE_ATOMIC
                 ], random.randint(1, 2))
                 mr_flags = 0
                 for i in flags:
                     mr_flags += i.value
                 try:
                     DmaBufMR(pd,
                              u.get_mr_length(),
                              mr_flags,
                              gpu=self.gpu,
                              gtt=self.gtt)
                 except PyverbsRDMAError as err:
                     assert 'Failed to register a dma-buf MR' in err.args[0]
                 else:
                     raise PyverbsRDMAError(
                         'Registered a dma-buf MR with illegal falgs')
    def test_query_gid_ex_bad_flow(self):
        """
        Test ibv_query_gid_ex() with an empty index
        """
        try:
            port_attr = self.ctx.query_port(self.ib_port)
            max_entries = 0
            for port_num in range(1, self.attr.phys_port_cnt + 1):
                attr = self.ctx.query_port(port_num)
                max_entries += attr.gid_tbl_len
            if max_entries > 0:
                gid_indices = {gid_entry.gid_index for gid_entry in
                               self.ctx.query_gid_table(max_entries) if gid_entry.port_num == self.ib_port}
            else:
                gid_indices = {}

            possible_indices = set(range(port_attr.gid_tbl_len)) if port_attr.gid_tbl_len > 1 else set()
            try:
                no_gid_index = possible_indices.difference(gid_indices).pop()
            except KeyError:
                # all indices are populated by GIDs
                raise unittest.SkipTest('All gid indices populated,'
                                        ' cannot check bad flow')

            self.ctx.query_gid_ex(port_num=self.ib_port, gid_index=no_gid_index)
        except PyverbsRDMAError as ex:
            if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]:
                raise unittest.SkipTest('ibv_query_gid_ex is not'
                                        ' supported on this device')
            self.assertEqual(ex.error_code, errno.ENODATA,
                             f'Got {os.strerror(ex.error_code)} but '
                             f'Expected {os.strerror(errno.ENODATA)}')
        else:
            raise PyverbsRDMAError('Successfully queried '
                                   f'non-existent gid index {no_gid_index}')
示例#7
0
def poll_cq(cq, count=1):
    """
    Poll <count> completions from the CQ.
    Note: This function calls the blocking poll() method of the CQ
    until <count> completions were received. Alternatively, gets a
    single CQ event when events are used.
    :param cq: CQ to poll from
    :param count: How many completions to poll
    :return: An array of work completions of length <count>, None
             when events are used
    """
    wcs = []
    channel = cq.comp_channel
    while count > 0:
        if channel:
            channel.get_cq_event(cq)
            cq.req_notify()
        nc, tmp_wcs = cq.poll(count)
        for wc in tmp_wcs:
            if wc.status != e.IBV_WC_SUCCESS:
                raise PyverbsRDMAError('Completion status is {s}'.format(
                    s=wc_status_to_str(wc.status)))
        count -= nc
        wcs.extend(tmp_wcs)
    return wcs
示例#8
0
    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)
示例#9
0
 def test_mlx5vfio_rc_qp_send_imm_traffic(self):
     """
     Opens one mlx5 vfio context, creates two DevX RC QPs on it, and modifies
     them to RTS state.
     Then does SEND_IMM traffic.
     """
     self.create_players()
     if self.server.is_eth():
         raise unittest.SkipTest(
             f'{self.__class__.__name__} is currently supported over IB only'
         )
     self.event_ex = []
     self.proc_events = True
     proc_events = Thread(target=self.vfio_processs_events)
     proc_events.start()
     # Move the DevX QPs ro RTS state
     self.pre_run()
     try:
         # Send traffic
         self.send_imm_traffic()
     finally:
         # Stop listening to events
         self.proc_events = False
         proc_events.join()
         if self.event_ex:
             raise PyverbsRDMAError(
                 f'Received unexpected vfio events: {self.event_ex}')
示例#10
0
 def _send_mad_cmd(self, ib_port, in_mad, op_mod):
     from tests.mlx5_prm_structs import MadIfcIn, MadIfcOut
     mad_ifc_in = MadIfcIn(op_mod=op_mod, port=ib_port, mad=in_mad)
     cmd_out = self.ctx.devx_general_cmd(mad_ifc_in, len(MadIfcOut()))
     mad_ifc_out = MadIfcOut(cmd_out)
     if mad_ifc_out.status:
         raise PyverbsRDMAError(f'Failed to send MAD with syndrome ({mad_ifc_out.syndrome})')
     return mad_ifc_out.mad
示例#11
0
    def query_lid(self):
        from tests.mlx5_prm_structs import QueryHcaVportContextIn, \
            QueryHcaVportContextOut, QueryHcaCapIn, QueryCmdHcaCapOut

        query_cap_in = QueryHcaCapIn(op_mod=0x1)
        query_cap_out = QueryCmdHcaCapOut(self.ctx.devx_general_cmd(
            query_cap_in, len(QueryCmdHcaCapOut())))
        if query_cap_out.status:
            raise PyverbsRDMAError('Failed to query general HCA CAPs with syndrome '
                                   f'({query_cap_out.syndrome}')
        port_num = self.ib_port if query_cap_out.capability.num_ports >= 2 else 0
        query_port_in = QueryHcaVportContextIn(port_num=port_num)
        query_port_out = QueryHcaVportContextOut(self.ctx.devx_general_cmd(
            query_port_in, len(QueryHcaVportContextOut())))
        if query_port_out.status:
            raise PyverbsRDMAError('Failed to query vport with syndrome '
                                   f'({query_port_out.syndrome})')
        self.lid = query_port_out.hca_vport_context.lid
示例#12
0
 def check_mkey(self, player, expected=dve.MLX5DV_MKEY_NO_ERR):
     """
     Check the player's mkey for a signature error.
     param player: Player to check.
     param expected: The expected result of the checking.
     """
     mkey_err = player.mkey.mkey_check()
     if mkey_err.err_type != expected:
         raise PyverbsRDMAError('MKEY check failed: '
                                f'expected err_type: {expected_type}, '
                                f'actual err_type: {mkey_err.err_type}')
示例#13
0
    def is_eth(self):
        from tests.mlx5_prm_structs import QueryHcaCapIn, \
            QueryCmdHcaCapOut

        query_cap_in = QueryHcaCapIn(op_mod=0x1)
        query_cap_out = QueryCmdHcaCapOut(self.ctx.devx_general_cmd(
            query_cap_in, len(QueryCmdHcaCapOut())))
        if query_cap_out.status:
            raise PyverbsRDMAError('Failed to query general HCA CAPs with syndrome '
                                   f'({query_cap_out.syndrome})')
        return query_cap_out.capability.port_type  # 0:IB, 1:ETH
示例#14
0
 def access_paos_register(self, paos_in, op_mod=0):  # op_mod: 0 - write / 1 - read
     from tests.mlx5_prm_structs import AccessPaosRegisterIn, \
         AccessPaosRegisterOut, DevxOps
     paos_reg_in = AccessPaosRegisterIn(op_mod=op_mod,
                                        register_id=DevxOps.MLX5_CMD_OP_ACCESS_REGISTER_PAOS,
                                        data=paos_in)
     cmd_out = self.ctx.devx_general_cmd(paos_reg_in, len(AccessPaosRegisterOut()))
     paos_reg_out = AccessPaosRegisterOut(cmd_out)
     if paos_reg_out.status:
         raise PyverbsRDMAError(f'Failed to access PAOS register ({paos_reg_out.syndrome})')
     return paos_reg_out.data
示例#15
0
 def test_mlx5vfio_async_event(self):
     """
     Opens one mlx5 vfio context, creates DevX EQ on it.
     Then activates the port and catches the port state change event.
     """
     self.create_async_players()
     if self.server.is_eth():
         raise unittest.SkipTest(f'{self.__class__.__name__} is currently supported over IB only')
     self.event_ex = []
     self.proc_events = True
     self.caught_event = False
     proc_events = Thread(target=self.vfio_process_events)
     proc_async_events = Thread(target=self.vfio_process_async_events)
     proc_events.start()
     proc_async_events.start()
     # Move the DevX QPs to RTS state
     self.pre_run()
     try:
         # Change port state
         self.server.change_port_state_with_registers(PortStatus.MLX5_PORT_UP)
         admin_status, oper_status = self.server.query_port_state_with_registers()
         start_state_t = time.perf_counter()
         while admin_status != PortStatus.MLX5_PORT_UP or oper_status != PortStatus.MLX5_PORT_UP:
             if time.perf_counter() - start_state_t >= PORT_STATE_TIMEOUT:
                 raise PyverbsRDMAError('Could not change the port state to UP')
             admin_status, oper_status = self.server.query_port_state_with_registers()
         start_state_t = time.perf_counter()
         while self.server.query_port_state_with_mads(self.ib_port) < PortState.ACTIVE:
             if time.perf_counter() - start_state_t >= PORT_STATE_TIMEOUT:
                 raise PyverbsRDMAError('Could not change the port state to ACTIVE')
             time.sleep(1)
     finally:
         # Stop listening to events
         self.proc_events = False
         proc_events.join()
         proc_async_events.join()
         if self.event_ex:
             raise PyverbsRDMAError(f'Received unexpected vfio events: {self.event_ex}')
         if not self.caught_event:
             raise PyverbsRDMAError('Failed to catch an async event')
示例#16
0
    def poll_cq(self):
        """
        Polls the CQ once and updates the consumer index upon success.
        The CQE opcode and owner bit are checked and verified.
        This method does busy-waiting as long as it gets an empty CQE, until a
        timeout of POLL_CQ_TIMEOUT seconds.
        """
        idx = self.qattr.cq.cons_idx % self.qattr.cq.ncqes
        cq_owner_flip = not (
            not (self.qattr.cq.cons_idx & self.qattr.cq.ncqes))
        cqe_start_addr = self.umems['cq'].umem_addr + (idx *
                                                       self.qattr.cq.cqe_size)
        cqe = None
        start_poll_t = time.perf_counter()
        while cqe is None:
            cqe = Mlx5Cqe64(cqe_start_addr)
            if (cqe.opcode == dve.MLX5_CQE_INVALID) or \
                    (cqe.owner ^ cq_owner_flip) or cqe.is_empty():
                if time.perf_counter() - start_poll_t >= POLL_CQ_TIMEOUT:
                    raise PyverbsRDMAError(
                        f'CQE #{self.qattr.cq.cons_idx} '
                        f'is empty or invalid:\n{cqe.dump()}')
                cqe = None

        # After CQE ownership check, must do memory barrier and re-read the CQE.
        dma.udma_from_dev_barrier()
        cqe = Mlx5Cqe64(cqe_start_addr)

        if cqe.opcode == dve.MLX5_CQE_RESP_ERR:
            raise PyverbsRDMAError(f'Got a CQE #{self.qattr.cq.cons_idx} '
                                   f'with responder error:\n{cqe.dump()}')
        elif cqe.opcode == dve.MLX5_CQE_REQ_ERR:
            raise PyverbsRDMAError(f'Got a CQE #{self.qattr.cq.cons_idx} '
                                   f'with requester error:\n{cqe.dump()}')

        self.qattr.cq.cons_idx += 1
        mem.writebe32(self.umems['cq_dbr'].umem_addr,
                      self.qattr.cq.cons_idx & 0xffffff, MLX5_CQ_SET_CI)
        return cqe
示例#17
0
 def get_device_list(self):
     lst = d.get_device_list()
     if len(lst) == 0:
         raise unittest.SkipTest('No IB device found')
     dev_name = self.config['dev']
     if dev_name:
         for dev in lst:
             if dev.name.decode() == dev_name:
                 lst = [dev]
                 break
         if len(lst) == 0:
             raise PyverbsRDMAError(f'No IB device with name {dev_name} found')
     return lst
示例#18
0
 def vfio_process_events(self):
     """
     Processes mlx5 vfio device events.
     This method should run from application thread to maintain the events.
     """
     # Server and client use the same context
     events_fd = self.server.ctx.get_events_fd()
     with select.epoll() as epoll_events:
         epoll_events.register(events_fd, select.EPOLLIN)
         while self.proc_events:
             for fd, event in epoll_events.poll(timeout=0.1):
                 if fd == events_fd:
                     if not (event & select.EPOLLIN):
                         self.event_ex.append(PyverbsRDMAError(f'Unexpected vfio event: {event}'))
                     self.server.ctx.process_events()
示例#19
0
 def test_query_port_bad_flow(self):
     """ Verify that querying non-existing ports fails as expected """
     lst = d.get_device_list()
     for dev in lst:
         with d.Context(name=dev.name.decode()) as ctx:
             num_ports = ctx.query_device().phys_port_cnt
             try:
                 port = num_ports + random.randint(1, 10)
                 ctx.query_port(port)
             except PyverbsRDMAError as e:
                 assert 'Failed to query port' in e.args[0]
                 assert 'Invalid argument' in e.args[0]
             else:
                 raise PyverbsRDMAError('Successfully queried non-existing port {p}'.\
                                        format(p=port))
示例#20
0
 def test_query_gid_table_bad_flow(self):
     """
     Test ibv_query_gid_table() with too small a buffer
     """
     try:
         self.ctx.query_gid_table(0)
     except PyverbsRDMAError as ex:
         if ex.error_code in [-errno.EOPNOTSUPP, -errno.EPROTONOSUPPORT]:
             raise unittest.SkipTest('ibv_query_gid_table is not'
                                     ' supported on this device')
         self.assertEqual(ex.error_code, -errno.EINVAL,
                          f'Got -{os.strerror(-ex.error_code)} but '
                          f'Expected -{os.strerror(errno.EINVAL)} ')
     else:
         raise PyverbsRDMAError('Successfully queried '
                                'gid_table with an insufficient buffer')
示例#21
0
    def process_async_events(self, fd):
        from tests.mlx5_prm_structs import EventType

        cc = 0
        ret = os.read(fd, 8)
        if not ret:
            raise PyverbsRDMAErrno('Failed to read FD')
        eqe = self.get_eqe(cc)
        while eqe:
            if eqe.event_type == EventType.PORT_STATE_CHANGE:
                self.logger.debug('Caught port state change event')
                return eqe.event_type
            elif eqe.event_type == EventType.CQ_ERROR:
                raise PyverbsRDMAError('Event type Error')
            cc = self.update_cc(cc + 1)
            eqe = self.get_eqe(cc)
        self.update_ci(cc, 1)
示例#22
0
    def vfio_process_async_events(self):
        """
        Processes mlx5 vfio device async events.
        This method should run from application thread to maintain the events.
        """
        from tests.mlx5_prm_structs import EventType

        # Server and client use the same context
        events_fd = self.server.msi_vector.fd
        with select.epoll() as epoll_events:
            epoll_events.register(events_fd, select.EPOLLIN)
            while self.proc_events:
                for fd, event in epoll_events.poll(timeout=0.1):
                    if fd == events_fd:
                        if not (event & select.EPOLLIN):
                            self.event_ex.append(PyverbsRDMAError(f'Unexpected vfio event: {event}'))
                        if self.server.process_async_events(events_fd) == EventType.PORT_STATE_CHANGE:
                            self.caught_event = True
示例#23
0
文件: mr.py 项目: rhiswell/rdma-core
 def test_reg_mr_bad_flags(self):
     """ Verify that illegal flags combination fails as expected """
     lst = d.get_device_list()
     for dev in lst:
         with d.Context(name=dev.name.decode()) as ctx:
             with PD(ctx) as pd:
                 flags = random.sample([
                     e.IBV_ACCESS_REMOTE_WRITE, e.IBV_ACCESS_REMOTE_ATOMIC
                 ], random.randint(1, 2))
                 mr_flags = 0
                 for i in flags:
                     mr_flags += i.value
                 try:
                     mr = MR(pd, u.get_mr_length(), mr_flags)
                 except PyverbsRDMAError as err:
                     assert 'Failed to register a MR' in err.args[0]
                 else:
                     raise PyverbsRDMAError(
                         'Registered a MR with illegal falgs')
示例#24
0
 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)
示例#25
0
 def create_uar(self):
     super().create_uar()
     self.uar['eq'] = Mlx5UAR(self.ctx, dve._MLX5DV_UAR_ALLOC_TYPE_NC)
     if not self.uar['eq'].page_id:
         raise PyverbsRDMAError('Failed to allocate UAR')