# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2020 NVIDIA Corporation . All rights reserved. See COPYING file

import unittest
import errno
import time

from tests.mlx5_base import Mlx5DcResources, Mlx5RDMATestCase, Mlx5DcStreamsRes
from pyverbs.pyverbs_error import PyverbsRDMAError
from pyverbs.providers.mlx5.mlx5dv import Mlx5QP
from pyverbs.libibverbs_enums import ibv_access_flags, ibv_qp_create_send_ops_flags, ibv_wr_opcode, \
    ibv_odp_transport_cap_bits, ibv_qp_attr_mask, ibv_qp_state
import tests.utils as u


class OdpDc(Mlx5DcResources):
    def create_mr(self):
        try:
            self.mr = u.create_custom_mr(self, ibv_access_flags.IBV_ACCESS_ON_DEMAND)
        except PyverbsRDMAError as ex:
            if ex.error_code == errno.EOPNOTSUPP:
                raise unittest.SkipTest('Reg ODP MR is not supported')
            raise ex


class DCTest(Mlx5RDMATestCase):
    def setUp(self):
        super().setUp()
        self.iters = 10
        self.server = None
        self.client = None
        self.traffic_args = None

    def sync_remote_attr(self):
        """
        Exchange the remote attributes between the server and the client.
        """
        super().sync_remote_attr()
        self.client.remote_dct_num = self.server.dct_qp.qp_num
        self.server.remote_dct_num = self.client.dct_qp.qp_num

    def test_dc_rdma_write(self):
        self.create_players(Mlx5DcResources, qp_count=2,
                            send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE)
        u.rdma_traffic(**self.traffic_args, new_send=True,
                       send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE)

    def test_dc_send(self):
        self.create_players(Mlx5DcResources, qp_count=2,
                            send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_SEND)
        u.traffic(**self.traffic_args, new_send=True,
                  send_op=ibv_wr_opcode.IBV_WR_SEND)

    def test_dc_atomic(self):
        self.create_players(Mlx5DcResources, qp_count=2,
                            send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_ATOMIC_FETCH_AND_ADD)
        client_max_log = self.client.ctx.query_mlx5_device().max_dc_rd_atom
        server_max_log = self.server.ctx.query_mlx5_device().max_dc_rd_atom
        u.atomic_traffic(**self.traffic_args, new_send=True,
                         send_op=ibv_wr_opcode.IBV_WR_ATOMIC_FETCH_AND_ADD,
                         client_wr=client_max_log, server_wr=server_max_log)

    def test_dc_ah_to_qp_mapping(self):
        self.create_players(Mlx5DcResources, qp_count=2,
                            send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_SEND)
        client_ah = u.get_global_ah(self.client, self.gid_index, self.ib_port)
        try:
            Mlx5QP.map_ah_to_qp(client_ah, self.server.qps[0].qp_num)
        except PyverbsRDMAError as ex:
            if ex.error_code == errno.EOPNOTSUPP:
                raise unittest.SkipTest('Mapping AH to QP is not supported')
            raise ex
        u.traffic(**self.traffic_args, new_send=True,
                  send_op=ibv_wr_opcode.IBV_WR_SEND)

    def check_odp_dc_support(self):
        """
        Check if the device supports ODP with DC.
        :raises SkipTest: In case ODP is not supported with DC
        """
        dc_odp_caps = self.server.ctx.query_mlx5_device().dc_odp_caps
        required_odp_caps = ibv_odp_transport_cap_bits.IBV_ODP_SUPPORT_SEND | \
                            ibv_odp_transport_cap_bits.IBV_ODP_SUPPORT_SRQ_RECV
        if required_odp_caps & dc_odp_caps != required_odp_caps:
            raise unittest.SkipTest('ODP is not supported using DC')

    def test_odp_dc_traffic(self):
        send_ops_flag = ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_SEND
        self.create_players(OdpDc, qp_count=2, send_ops_flags=send_ops_flag)
        self.check_odp_dc_support()
        u.traffic(**self.traffic_args, new_send=True,
                  send_op=ibv_wr_opcode.IBV_WR_SEND)

    def test_dc_rdma_write_stream(self):
        """
        Check good flow of DCS.
        Calculate stream_id for DCS test by setting same stream id
        twice for WR and after increase it. Setting goes by loop
        and after stream_id is more than number of concurrent
        streams + 1 then stream_id returns to 1.
        :raises SkipTest: In case DCI is not supported with HW
        """
        self.create_players(Mlx5DcStreamsRes, qp_count=2,
                            send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE)
        u.rdma_traffic(**self.traffic_args, new_send=True,
                       send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE)

    def test_dc_stream_qp_recovery(self):
        """
        Test DC QP error state transition with stream channel error accumulation.
        Creates DC QPs with restricted MR access and generates remote access errors
        via RDMA_WRITE operations. Verifies QP transitions to ERR state after enough
        channels entered error mode. Validates QP recovery after reset.
        """
        self.create_players(Mlx5DcStreamsRes, qp_count=2,
                            send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE,
                            mr_access=ibv_access_flags.IBV_ACCESS_LOCAL_WRITE)
        qp_idx = 0
        error_threshold = self.client.dcis[qp_idx]['errored']
        u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND)
        for _ in range(error_threshold):
            with self.assertRaisesRegex(PyverbsRDMAError, r'Remote access error'):
                u.rdma_traffic(**self.traffic_args, new_send=True,
                               send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE)
        # Poll QP state with timeout: it takes time to transition QP to ERR after errors
        qp_in_err_state = False
        start = time.perf_counter()
        while time.perf_counter() - start < 1.0:
            qp_attr, _ = self.client.qps[qp_idx].query(ibv_qp_attr_mask.IBV_QP_STATE)
            if qp_attr.cur_qp_state == ibv_qp_state.IBV_QPS_ERR:
                qp_in_err_state = True
                break
        if not qp_in_err_state:
            raise PyverbsRDMAError(f'QP is not in ERR state after {error_threshold} errors')
        for qp_idx in range(self.client.qp_count):
            self.client.reset_qp(qp_idx)
        for qp_idx in range(self.server.qp_count):
            self.server.reset_qp(qp_idx)
        u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND)

    def test_dc_stream_ids_recovery(self):
        """
        Test DC stream ID reset functionality after remote access errors.
        Creates DC QPs with restricted MR access and generates
        remote access errors via RDMA_WRITE operations. After each error, resets
        the stream ID and verifies QP remains functional.
        Validates normal SEND traffic continues to work after stream resets.
        """
        self.create_players(Mlx5DcStreamsRes, qp_count=2,
                            send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE,
                            mr_access=ibv_access_flags.IBV_ACCESS_LOCAL_WRITE)
        qp_idx = 0
        error_threshold = self.client.dcis[qp_idx]['errored']
        u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND)
        for _ in range(error_threshold):
            with self.assertRaisesRegex(PyverbsRDMAError, r'Remote access error'):
                u.rdma_traffic(**self.traffic_args, new_send=True,
                            send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE)
            self.client.dci_reset_stream_id(qp_idx)
        qp_attr, _ = self.client.qps[qp_idx].query(ibv_qp_attr_mask.IBV_QP_STATE)
        if qp_attr.cur_qp_state == ibv_qp_state.IBV_QPS_ERR:
            raise PyverbsRDMAError('QP is in ERR state after reset stream id')
        u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND)
