# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2019 Mellanox Technologies, Inc. All rights reserved.  See COPYING file
# Copyright (c) 2020 Intel Corporation. All rights reserved. See COPYING file
"""
Provide some useful helper function for pyverbs' tests.
"""
from itertools import combinations as com
import errno
import subprocess
import unittest
import random
import socket
import struct
import string
import glob
import time
import os

from pyverbs.pyverbs_error import PyverbsError, PyverbsRDMAError, PyverbsUserError
from pyverbs.providers.mlx5.mlx5dv import Mlx5Context, Mlx5DVContextAttr
from pyverbs.qp import QPCap, QPInitAttr, QPInitAttrEx, QPAttr, QPEx, QP
from tests.mlx5_base import Mlx5DcResources, Mlx5DcStreamsRes
from tests.base import XRCResources, DCT_KEY, MLNX_VENDOR_ID
from pyverbs.addr import AHAttr, AH, GlobalRoute
from pyverbs.providers.efa.efadv import EfaCQ
from pyverbs.wr import SGE, SendWR, RecvWR
from pyverbs.base import PyverbsRDMAErrno
from tests.efa_base import SRDResources
from pyverbs.cq import PollCqAttr, CQEX
from pyverbs.mr import MW, MWBindInfo
from pyverbs.mem_alloc import madvise
import pyverbs.device as d
import pyverbs.enums as e
from pyverbs.mr import MR


MAX_MR_SIZE = 4194304
# Some HWs limit DM address and length alignment to 4 for read and write
# operations. Use a minimal length and alignment that respect that.
# For creation purposes use random alignments. As this is log2 of address
# alignment, no need for large numbers.
MIN_DM_SIZE = 4
DM_ALIGNMENT = 4
MIN_DM_LOG_ALIGN = 0
MAX_DM_LOG_ALIGN = 6
# Raw Packet QP supports TSO header, which creates a larger send WQE.
MAX_RAW_PACKET_SEND_WR = 2500
GRH_SIZE = 40
IMM_DATA = 1234
POLL_CQ_TIMEOUT = 10  # In seconds


class MatchCriteriaEnable:
    NONE = 0
    OUTER = 1
    MISC = 1 << 1
    INNER = 1 << 2
    MISC_2 = 1 << 3
    MISC_3 = 1 << 4


class PacketConsts:
    """
    Class to hold constant packets' values.
    """
    ETHER_HEADER_SIZE = 14
    IPV4_HEADER_SIZE = 20
    IPV6_HEADER_SIZE = 40
    UDP_HEADER_SIZE = 8
    TCP_HEADER_SIZE = 20
    VLAN_HEADER_SIZE = 4
    TCP_HEADER_SIZE_WORDS = 5
    IP_V4 = 4
    IP_V6 = 6
    TCP_PROTO = 'tcp'
    UDP_PROTO = 'udp'
    IP_V4_FLAGS = 2  # Don't fragment is set
    TTL_HOP_LIMIT = 64
    IHL = 5
    # Hardcoded values for flow matchers
    ETHER_TYPE_ETH = 0x6558
    ETHER_TYPE_IPV4 = 0x800
    MAC_MASK = "ff:ff:ff:ff:ff:ff"
    ETHER_TYPE_IPV6 = 0x86DD
    SRC_MAC = "24:8a:07:a5:28:c8"
    # DST mac must be multicast
    DST_MAC = "01:50:56:19:20:a7"
    SRC_IP = "1.1.1.1"
    DST_IP = "2.2.2.2"
    SRC_PORT = 1234
    DST_PORT = 5678
    SRC_IP6 = "a0a1::a2a3:a4a5:a6a7:a8a9"
    DST_IP6 = "b0b1::b2b3:b4b5:b6b7:b8b9"
    SEQ_NUM = 1
    WINDOW_SIZE = 65535
    VXLAN_PORT = 4789
    VXLAN_VNI = 7777777
    VXLAN_FLAGS = 0x8
    VXLAN_HEADER_SIZE = 8
    VLAN_TPID = 0x8100
    VLAN_PRIO = 5
    VLAN_CFI = 1
    VLAN_ID = 0xc0c
    GRE_VER = 1
    GRE_FLAGS = 2
    GRE_KEY = 0x12345678
    GENEVE_VNI = 2
    GENEVE_OAM = 0
    GENEVE_PORT = 6081
    BTH_HEADER_SIZE = 16
    BTH_OPCODE = 0x81
    BTH_DST_QP = 0xd2
    BTH_A = 0x1
    BTH_PARTITION_KEY = 0xffff
    BTH_BECN = 1
    ROCE_PORT = 4791


def get_mr_length():
    """
    Provide a random value for MR length. We avoid large buffers as these
    allocations typically fails.
    We use random.random() instead of randrange() or randint() due to
    performance issues when generating very large pseudo random numbers.
    :return: A random MR length
    """
    return int(MAX_MR_SIZE * random.random())


def filter_illegal_access_flags(element):
    """
    Helper function to filter illegal access flags combinations
    :param element: A list of access flags to check
    :return: True if this list is legal, else False
    """
    if e.IBV_ACCESS_REMOTE_ATOMIC in element or e.IBV_ACCESS_REMOTE_WRITE in element:
        if not e.IBV_ACCESS_LOCAL_WRITE in element:
            return False
    return True


def get_access_flags(ctx):
    """
    Provide an array of random legal access flags for an MR.
    Since remote write and remote atomic require local write permission, if
    one of them is randomly selected without local write, local write will be
    added as well.
    After verifying that the flags selection is legal, it is appended to an
    array, assuming it wasn't previously appended.
    :param ctx: Device Context to check capabilities
    :param num: Size of initial collection
    :return: A random legal value for MR flags
    """
    attr = ctx.query_device()
    attr_ex = ctx.query_device_ex()
    vals = list(e.ibv_access_flags)
    if not attr_ex.odp_caps.general_caps & e.IBV_ODP_SUPPORT:
        vals.remove(e.IBV_ACCESS_ON_DEMAND)
    if not attr.device_cap_flags & e.IBV_DEVICE_MEM_WINDOW:
        vals.remove(e.IBV_ACCESS_MW_BIND)
    if not attr.atomic_caps & e.IBV_ATOMIC_HCA:
        vals.remove(e.IBV_ACCESS_REMOTE_ATOMIC)
    arr = []
    for i in range(1, len(vals)):
        tmp = list(com(vals, i))
        tmp = filter(filter_illegal_access_flags, tmp)
        for t in tmp:  # Iterate legal combinations and bitwise OR them
            val = 0
            for flag in t:
                val += flag.value
            arr.append(val)
    return arr


def get_dmabuf_access_flags(ctx):
    """
    Similar to get_access_flags, except that dma-buf MR only support
    a subset of the flags.
    :param ctx: Device Context to check capabilities
    :return: A random legal value for MR flags
    """
    attr = ctx.query_device()
    vals = [e.IBV_ACCESS_LOCAL_WRITE, e.IBV_ACCESS_REMOTE_WRITE,
            e.IBV_ACCESS_REMOTE_READ, e.IBV_ACCESS_REMOTE_ATOMIC,
            e.IBV_ACCESS_RELAXED_ORDERING]
    if not attr.atomic_caps & e.IBV_ATOMIC_HCA:
        vals.remove(e.IBV_ACCESS_REMOTE_ATOMIC)
    arr = []
    for i in range(1, len(vals)):
        tmp = list(com(vals, i))
        tmp = filter(filter_illegal_access_flags, tmp)
        for t in tmp:  # Iterate legal combinations and bitwise OR them
            val = 0
            for flag in t:
                val += flag.value
            arr.append(val)
    return arr


def get_dm_attrs(dm_len):
    """
    Initializes an AllocDmAttr member with the given length and random
    alignment. It currently sets comp_mask = 0 since other comp_mask values
    are not supported.
    :param dm_len:
    :return: An initialized AllocDmAttr object
    """
    align = random.randint(MIN_DM_LOG_ALIGN, MAX_DM_LOG_ALIGN)
    return d.AllocDmAttr(dm_len, align, 0)


def sample(coll):
    """
    Returns a random-length subset of the given collection.
    :param coll: The collection to sample
    :return: A subset of <collection>
    """
    return random.sample(coll, int((len(coll) + 1) * random.random()))


def random_qp_cap(attr):
    """
    Initializes a QPCap object with valid values based on the device's
    attributes.
    It doesn't check the max WR limits since they're reported for smaller WR
    sizes.
    :return: A QPCap object
    """
    # We use significantly smaller values than those in device attributes.
    # The attributes reported by the device don't take into account possible
    # larger WQEs that include e.g. memory window.
    send_wr = random.randint(1, int(attr.max_qp_wr / 8))
    recv_wr = random.randint(1, int(attr.max_qp_wr / 8))
    send_sge = random.randint(1, int(attr.max_sge / 2))
    recv_sge = random.randint(1, int(attr.max_sge / 2))
    return QPCap(send_wr, recv_wr, send_sge, recv_sge)


def random_qp_create_mask(qpt, attr_ex):
    """
    Select a random sublist of ibv_qp_init_attr_mask. Some of the options are
    not yet supported by pyverbs and will not be returned. TSO support is
    checked for the device and the QP type. If it doesn't exist, TSO will not
    be set.
    :param qpt: Current QP type
    :param attr_ex: Extended device attributes for capability checks
    :return: A sublist of ibv_qp_init_attr_mask
    """
    has_tso = attr_ex.tso_caps.max_tso > 0 and \
        attr_ex.tso_caps.supported_qpts & 1 << qpt
    supp_flags = [e.IBV_QP_INIT_ATTR_CREATE_FLAGS,
                  e.IBV_QP_INIT_ATTR_MAX_TSO_HEADER]
    # Either PD or XRCD flag is needed, XRCD is not supported yet
    selected = sample(supp_flags)
    selected.append(e.IBV_QP_INIT_ATTR_PD)
    if e.IBV_QP_INIT_ATTR_MAX_TSO_HEADER in selected and not has_tso:
        selected.remove(e.IBV_QP_INIT_ATTR_MAX_TSO_HEADER)
    mask = 0
    for s in selected:
        mask += s.value
    return mask


def get_create_qp_flags_raw_packet(attr_ex):
    """
    Select random QP creation flags for Raw Packet QP. Filter out unsupported
    flags prior to selection.
    :param attr_ex: Device extended attributes to check capabilities
    :return: A random combination of QP creation flags
    """
    has_fcs = attr_ex.device_cap_flags_ex & e._IBV_DEVICE_RAW_SCATTER_FCS
    has_cvlan = attr_ex.raw_packet_caps & e.IBV_RAW_PACKET_CAP_CVLAN_STRIPPING
    has_padding = attr_ex.device_cap_flags_ex & \
        e._IBV_DEVICE_PCI_WRITE_END_PADDING
    l = list(e.ibv_qp_create_flags)
    l.remove(e.IBV_QP_CREATE_SOURCE_QPN)  # UD only
    if not has_fcs:
        l.remove(e.IBV_QP_CREATE_SCATTER_FCS)
    if not has_cvlan:
        l.remove(e.IBV_QP_CREATE_CVLAN_STRIPPING)
    if not has_padding:
        l.remove(e.IBV_QP_CREATE_PCI_WRITE_END_PADDING)
    flags = sample(l)
    val = 0
    for i in flags:
        val |= i.value
    return val


def random_valid_qp_create_flags(qpt, attr, attr_ex):
    """
    Select a random sublist of ibv_qp_create_flags according to the QP type.
    :param qpt: Current QP type
    :param attr_ex: Used for Raw Packet QP to check device capabilities
    :return: A sublist of ibv_qp_create_flags
    """
     # Most HCAs doesn't support any create_flags so far except mlx4/mlx5
    if attr.vendor_id != MLNX_VENDOR_ID:
        return 0

    if qpt == e.IBV_QPT_RAW_PACKET:
        return get_create_qp_flags_raw_packet(attr_ex)
    elif qpt == e.IBV_QPT_UD:
        # IBV_QP_CREATE_SOURCE_QPN is only supported by mlx5 driver and is not
        # to be check in unittests.
        return random.choice([0, 2])  # IBV_QP_CREATE_BLOCK_SELF_MCAST_LB
    else:
        return 0


def random_qp_init_attr_ex(attr_ex, attr, qpt=None):
    """
    Create a random-valued QPInitAttrEx object with the given QP type.
    QP type affects QP capabilities, so allow users to set it and still get
    valid attributes.
    :param attr_ex: Extended device attributes for capability checks
    :param attr: Device attributes for capability checks
    :param qpt: Requested QP type
    :return: A valid initialized QPInitAttrEx object
    """
    max_tso = 0
    if qpt is None:
        qpt = random.choice([e.IBV_QPT_RC, e.IBV_QPT_UC, e.IBV_QPT_UD,
                             e.IBV_QPT_RAW_PACKET])
    qp_cap = random_qp_cap(attr)
    if qpt == e.IBV_QPT_RAW_PACKET and \
       qp_cap.max_send_wr > MAX_RAW_PACKET_SEND_WR:
        qp_cap.max_send_wr = MAX_RAW_PACKET_SEND_WR
    sig = random.randint(0, 1)
    mask = random_qp_create_mask(qpt, attr_ex)
    if mask & e.IBV_QP_INIT_ATTR_CREATE_FLAGS:
        cflags = random_valid_qp_create_flags(qpt, attr, attr_ex)
    else:
        cflags = 0
    if mask & e.IBV_QP_INIT_ATTR_MAX_TSO_HEADER:
        if qpt != e.IBV_QPT_RAW_PACKET:
            mask -= e.IBV_QP_INIT_ATTR_MAX_TSO_HEADER
        else:
            max_tso = \
                random.randint(16, int(attr_ex.tso_caps.max_tso / 800))
    qia = QPInitAttrEx(qp_type=qpt, cap=qp_cap, sq_sig_all=sig, comp_mask=mask,
                       create_flags=cflags, max_tso_header=max_tso)
    if mask & e.IBV_QP_INIT_ATTR_MAX_TSO_HEADER:
        # TSO increases send WQE size, let's be on the safe side
        qia.cap.max_send_sge = 2
    return qia


def get_qp_init_attr(cq, attr):
    """
    Creates a QPInitAttr object with a QP type of the provided <qpts> array and
    other random values.
    :param cq: CQ to be used as send and receive CQ
    :param attr: Device attributes for capability checks
    :return: An initialized QPInitAttr object
    """
    qp_cap = random_qp_cap(attr)
    sig = random.randint(0, 1)
    return QPInitAttr(scq=cq, rcq=cq, cap=qp_cap, sq_sig_all=sig)


def wc_status_to_str(status):
    try:
        return \
            {0: 'Success', 1: 'Local length error',
             2: 'local QP operation error', 3: 'Local EEC operation error',
             4: 'Local protection error', 5: 'WR flush error',
             6: 'Memory window bind error', 7: 'Bad response error',
             8: 'Local access error', 9: 'Remote invalidate request error',
             10: 'Remote access error', 11: 'Remote operation error',
             12: 'Retry exceeded', 13: 'RNR retry exceeded',
             14: 'Local RDD violation error',
             15: 'Remote invalidate RD request error',
             16: 'Remote aort error', 17: 'Invalidate EECN error',
             18: 'Invalidate EEC state error', 19: 'Fatal error',
             20: 'Response timeout error', 21: 'General error'}[status]
    except KeyError:
        return 'Unknown WC status ({s})'.format(s=status)


def create_custom_mr(agr_obj, additional_access_flags=0, size=None, user_addr=None):
    """
    Creates a memory region using the aggregation object's PD.
    If size is None, the agr_obj's message size is used to set the MR's size.
    The access flags are local write and the additional_access_flags.
    :param agr_obj: The aggregation object that creates the MR
    :param additional_access_flags: Addition access flags to set in the MR
    :param size: MR's length. If None, agr_obj.msg_size is used.
    :param user_addr: The MR's buffer address. If None, the buffer will be allocated by pyverbs.
    """
    mr_length = size if size else agr_obj.msg_size
    try:
        return MR(agr_obj.pd, mr_length,
                  e.IBV_ACCESS_LOCAL_WRITE | additional_access_flags, address=user_addr)
    except PyverbsRDMAError as ex:
        if ex.error_code == errno.EOPNOTSUPP:
                raise unittest.SkipTest(f'Create custom mr with additional access flags {additional_access_flags} is not supported')
        raise ex

# Traffic helpers

def get_send_elements(agr_obj, is_server, opcode=e.IBV_WR_SEND):
    """
    Creates a single SGE and a single Send WR for agr_obj's QP type. The content
    of the message is either 's' for server side or 'c' for client side.
    :param agr_obj: Aggregation object which contains all resources necessary
    :param is_server: Indicates whether this is server or client side
    :return: send wr and its SGE
    """
    if hasattr(agr_obj, 'use_mixed_mr') and agr_obj.use_mixed_mr:
        return get_send_elements_mixed_mr(agr_obj, is_server, opcode)
    if opcode == e.IBV_WR_ATOMIC_WRITE:
        atomic_wr = agr_obj.msg_size * (b's' if is_server else b'c')
        return None, atomic_wr

    qp_type = agr_obj.sqp_lst[0].qp_type if isinstance(agr_obj, XRCResources) \
                else agr_obj.qp.qp_type
    offset = GRH_SIZE if qp_type == e.IBV_QPT_UD else 0
    msg = (agr_obj.msg_size + offset) * ('s' if is_server else 'c')
    agr_obj.mem_write(msg, agr_obj.msg_size + offset)
    sge = SGE(agr_obj.mr.buf + offset, agr_obj.msg_size, agr_obj.mr_lkey)
    send_wr = SendWR(opcode=opcode, num_sge=1, sg=[sge])
    if opcode in [e.IBV_WR_RDMA_WRITE, e.IBV_WR_RDMA_WRITE_WITH_IMM, e.IBV_WR_RDMA_READ]:
        send_wr.set_wr_rdma(int(agr_obj.rkey), int(agr_obj.raddr))
    return send_wr, sge


def get_send_elements_mixed_mr(agr_obj, is_server, opcode=e.IBV_WR_SEND):
    """
    Creates 2 SGEs and a single Send WR for agr_obj's QP type. There are 2 messages,
    one for each MR. The content of the message is either 's' for server side or 'c'
    for client side.
    :param agr_obj: Aggregation object which contains all resources necessary
    :param is_server: Indicates whether this is server or client side
    :param opcode: send WR opcode
    :return: send wr and its SG list
    """
    msg = (agr_obj.msg_size) * ('s' if is_server else 'c')
    agr_obj.mr.write(msg, agr_obj.msg_size)
    agr_obj.non_odp_mr.write(msg, agr_obj.msg_size)
    sge1 = SGE(agr_obj.mr.buf, agr_obj.msg_size, agr_obj.mr.lkey)
    sge2 = SGE(agr_obj.non_odp_mr.buf, agr_obj.msg_size, agr_obj.non_odp_mr.lkey)
    send_wr = SendWR(opcode=opcode, num_sge=2, sg=[sge1, sge2])
    return send_wr, [sge1, sge2]


def get_recv_wr(agr_obj):
    """
    Creates a single SGE Recv WR for agr_obj's QP type. In case of mixed MRs,
    creates 2 SGEs accordingly.
    :param agr_obj: Aggregation object which contains all resources necessary
    :return: recv wr
    """
    qp_type = agr_obj.rqp_lst[0].qp_type if isinstance(agr_obj, XRCResources) \
        else agr_obj.qp.qp_type if isinstance(agr_obj.qp, QP) else None
    mr = agr_obj.mr
    length = agr_obj.msg_size + GRH_SIZE if qp_type == e.IBV_QPT_UD \
             else agr_obj.msg_size
    recv_sgl = [SGE(mr.buf, length, mr.lkey)]
    if hasattr(agr_obj, 'use_mixed_mr') and agr_obj.use_mixed_mr:
        sec_mr = agr_obj.non_odp_mr
        recv_sgl.append(SGE(sec_mr.buf,length,sec_mr.lkey))
    return RecvWR(sg=recv_sgl, num_sge=len(recv_sgl))


def get_global_ah(agr_obj, gid_index, port):
    gr = GlobalRoute(dgid=agr_obj.ctx.query_gid(port, gid_index),
                     sgid_index=gid_index)
    ah_attr = AHAttr(port_num=port, is_global=1, gr=gr,
                     dlid=agr_obj.port_attr.lid)
    return AH(agr_obj.pd, attr=ah_attr)


def get_global_route(ctx, gid_index=0, port_num=1):
    """
    Queries the provided Context's gid <gid_index> and creates a GlobalRoute
    object with sgid_index <gid_index> and the queried GID as dgid.
    :param ctx: Context object to query
    :param gid_index: GID index to query and use. Default: 0, as it's always
                      valid
    :param port_num: Number of the port to query. Default: 1
    :return: GlobalRoute object
    """
    if ctx.query_port(port_num).gid_tbl_len == 0:
        raise unittest.SkipTest(f'Not supported without GID table')
    gid = ctx.query_gid(port_num, gid_index)
    gr = GlobalRoute(dgid=gid, sgid_index=gid_index)
    return gr


def xrc_post_send(agr_obj, qp_num, send_object, send_op=None):
    agr_obj.qps = agr_obj.sqp_lst
    if send_op:
        post_send_ex(agr_obj, send_object, send_op)
    else:
        post_send(agr_obj, send_object)


def post_send_ex(agr_obj, send_object, send_op=None, qp_idx=0, ah=None, **kwargs):
    qp = agr_obj.qps[qp_idx]
    qp_type = qp.qp_type
    qp.wr_start()
    qp.wr_id = 0x123
    qp.wr_flags = e.IBV_SEND_SIGNALED
    if send_op == e.IBV_WR_SEND:
        qp.wr_send()
    elif send_op == e.IBV_WR_RDMA_WRITE:
        qp.wr_rdma_write(agr_obj.rkey, agr_obj.raddr)
    elif send_op == e.IBV_WR_SEND_WITH_IMM:
        qp.wr_send_imm(IMM_DATA)
    elif send_op == e.IBV_WR_RDMA_WRITE_WITH_IMM:
        qp.wr_rdma_write_imm(agr_obj.rkey, agr_obj.raddr, IMM_DATA)
    elif send_op == e.IBV_WR_ATOMIC_WRITE:
        qp.wr_atomic_write(agr_obj.rkey, agr_obj.raddr, send_object)
    elif send_op == e.IBV_WR_FLUSH:
        qp.wr_flush(agr_obj.rkey, agr_obj.raddr, agr_obj.msg_size,
                    agr_obj.ptype, agr_obj.level)
    elif send_op == e.IBV_WR_RDMA_READ:
        qp.wr_rdma_read(agr_obj.rkey, agr_obj.raddr)
    elif send_op == e.IBV_WR_ATOMIC_CMP_AND_SWP:
        cmp_add = kwargs.get('cmp_add')
        swp = kwargs.get('swap')
        qp.wr_atomic_cmp_swp(agr_obj.rkey, agr_obj.raddr,
                             int8b_from_int(cmp_add), int8b_from_int(swp))
    elif send_op == e.IBV_WR_ATOMIC_FETCH_AND_ADD:
        cmp_add = kwargs.get('cmp_add')
        qp.wr_atomic_fetch_add(agr_obj.rkey, agr_obj.raddr,
                               int8b_from_int(cmp_add))
    elif send_op == e.IBV_WR_BIND_MW:
        bind_info = MWBindInfo(agr_obj.mr, agr_obj.mr.buf, agr_obj.mr.rkey,
                               e.IBV_ACCESS_REMOTE_WRITE)
        mw = MW(agr_obj.pd, mw_type=e.IBV_MW_TYPE_2)
        # A new rkey is needed to be set into bind_info, modify rkey
        qp.wr_bind_mw(mw, agr_obj.mr.rkey + 12, bind_info)
        qp.wr_send()
    if qp_type == e.IBV_QPT_UD:
        qp.wr_set_ud_addr(ah, agr_obj.rqps_num[qp_idx], agr_obj.UD_QKEY)
    if isinstance(agr_obj, SRDResources):
        qp.wr_set_ud_addr(ah, agr_obj.rqps_num[qp_idx], agr_obj.SRD_QKEY)
    if qp_type == e.IBV_QPT_XRC_SEND:
        qp.wr_set_xrc_srqn(agr_obj.remote_srqn)
    if hasattr(agr_obj, 'remote_dct_num'):
        if isinstance(agr_obj, Mlx5DcStreamsRes):
            stream_id = agr_obj.generate_stream_id(qp_idx)
            agr_obj.check_bad_flow(qp_idx)
            qp.wr_set_dc_addr_stream(ah, agr_obj.remote_dct_num, DCT_KEY,
                                     stream_id)
        else:
            qp.wr_set_dc_addr(ah, agr_obj.remote_dct_num, DCT_KEY)
    if send_op != e.IBV_WR_ATOMIC_WRITE and \
            send_op != e.IBV_WR_FLUSH:
        qp.wr_set_sge(send_object)
    qp.wr_complete()


def post_send(agr_obj, send_wr, qp_idx=0, ah=None, is_imm=False):
    """
    Post a single send WR to the QP. Post_send's second parameter (send bad wr)
    is ignored for simplicity. For UD traffic an address vector is added as
    well.
    :param agr_obj: aggregation object which contains all resources necessary
    :param send_wr: Send work request to post send
    :param qp_idx: QP index to use
    :param ah: The destination address handle
    :param is_imm: If True, send with imm_data, relevant for old post send API
    :return: None
    """
    qp_type = agr_obj.qp.qp_type
    if is_imm:
        send_wr.imm_data = socket.htonl(IMM_DATA)
    if qp_type == e.IBV_QPT_UD:
        send_wr.set_wr_ud(ah, agr_obj.rqps_num[qp_idx], agr_obj.UD_QKEY)
    if isinstance(agr_obj, SRDResources):
        send_wr.set_wr_ud(ah, agr_obj.rqps_num[qp_idx], agr_obj.SRD_QKEY)
    agr_obj.qps[qp_idx].post_send(send_wr, None)


def post_recv(agr_obj, recv_wr, qp_idx=0 ,num_wqes=1):
    """
    Call the QP's post_recv() method <num_wqes> times. Post_recv's second
    parameter (recv bad wr) is ignored for simplicity.
    :param recv_wr: Receive work request to post
    :param qp_idx: QP index which posts receive work request
    :param num_wqes: Number of WQEs to post
    :return: None
    """
    receive_queue = agr_obj.srq if agr_obj.srq else agr_obj.qps[qp_idx]
    for _ in range(num_wqes):
        if isinstance(receive_queue, QPEx) and receive_queue.ind_table:
            for wq in receive_queue.ind_table.wqs:
                wq.post_recv(recv_wr, None)
        else:
            receive_queue.post_recv(recv_wr, None)


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
    start_poll_t = time.perf_counter()
    while count > 0 and (time.perf_counter() - start_poll_t < POLL_CQ_TIMEOUT):
        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:
                wcs.append(wc)
                return wcs
            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)

    if count > 0:
        raise PyverbsError(f'Got timeout on polling ({count} CQEs remaining)')

    return wcs


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 = _poll_cq(cq, count, data)
    if wcs[0].status != e.IBV_WC_SUCCESS:
        raise PyverbsRDMAError(f'Completion status is {wc_status_to_str(wcs[0].status)}')

    return wcs


def poll_cq_ex(cqex, count=1, data=None, sgid=None):
    """
    Poll <count> completions from the extended CQ.
    :param cq: CQEX 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, either a list of immediate data or
                 one value
    :param sgid: In case of EFA receive completion, the sgid to be compared
                 after poll
    :return: WR id order received
    """
    wr_id_order = []
    iters = count
    try:
        start_poll_t = time.perf_counter()
        poll_attr = PollCqAttr()
        ret = cqex.start_poll(poll_attr)
        while ret == 2 and (time.perf_counter() - start_poll_t < POLL_CQ_TIMEOUT):
            ret = cqex.start_poll(poll_attr)
        if ret != 0:
            raise PyverbsRDMAErrno('Failed to poll CQ')
        wr_id_order.append(cqex.wr_id)
        count -= 1
        if cqex.status != e.IBV_WC_SUCCESS:
            raise PyverbsRDMAErrno('Completion status is {s}'.
                                   format(s=cqex.status))
        if data:
            imm_data = data if not isinstance(data, list) else data[iters - count - 1]
            assert imm_data == socket.ntohl(cqex.read_imm_data())

        if isinstance(cqex, EfaCQ):
            if sgid is not None and cqex.read_opcode() == e.IBV_WC_RECV:
                assert sgid.gid == cqex.read_sgid().gid
        # Now poll the rest of the packets
        while count > 0 and (time.perf_counter() - start_poll_t < POLL_CQ_TIMEOUT):
            ret = cqex.poll_next()
            while ret == 2:
                ret = cqex.poll_next()
            if ret != 0:
                raise PyverbsRDMAErrno('Failed to poll CQ')
            if cqex.status != e.IBV_WC_SUCCESS:
                raise PyverbsRDMAErrno('Completion status is {s}'.
                                       format(s=cqex.status))
            count -= 1
            wr_id_order.append(cqex.wr_id)
            if data:
                imm_data = data if not isinstance(data, list) else data[iters - count - 1]
                assert imm_data == socket.ntohl(cqex.read_imm_data())

            if isinstance(cqex, EfaCQ):
                if sgid is not None and cqex.read_opcode() == e.IBV_WC_RECV:
                    assert sgid.gid == cqex.read_sgid().gid
        if count > 0:
            raise PyverbsError(f'Got timeout on polling ({count} CQEs remaining)')
    finally:
        cqex.end_poll()
    return wr_id_order


def validate(received_str, is_server, msg_size):
    """
    Validates the received buffer against the expected result.
    The application should set client's send buffer to 'c's and the
    server's send buffer to 's's.
    If the expected buffer is different than the actual, an exception will
    be raised.
    :param received_str: The received buffer to check
    :param is_server: Indicates whether this is the server (receiver) or
                      client side
    :param msg_size: the message size of the received packet
    :return: None
    """
    expected_str = msg_size * ('c' if is_server else 's')
    received_str = received_str.decode()
    if received_str[0:msg_size] == \
            expected_str[0:msg_size]:
        return
    else:
        raise PyverbsError(
            'Data validation failure: expected {exp}, received {rcv}'.
                format(exp=expected_str, rcv=received_str))


def send(agr_obj, send_object, send_op=None, new_send=False, qp_idx=0, ah=None, is_imm=False,
         **kwargs):
    if isinstance(agr_obj, XRCResources):
        agr_obj.qps = agr_obj.sqp_lst
    if new_send:
        return post_send_ex(agr_obj, send_object, send_op, qp_idx, ah, **kwargs)
    return post_send(agr_obj, send_object, qp_idx, ah, is_imm)


def traffic_poll_at_once(test, msg_size, iterations=10, opcode=e.IBV_WR_SEND):
    """
    Execute traffic between two peers iterations times:
    - Create receive resources and then post recv
    - Create send resources and then post send
    - Poll client and server all cqes at once
    - Compare received buffer with the expected one and validate
    :param test: Test object with client and server.
    :param msg_size: Size of a packet.
    :param iterations: Number of packets to send/recv.
    :param opcode: Send opcode. Currently it supports SEND and
                   RDMA_WRITE_WITH_IMM opcodes only.
    """
    imm_data_exp = []

    for i in range(iterations):
        recv_sge = SGE(test.server.mr.buf + (msg_size * i), msg_size, test.server.mr.lkey)
        recv_wr = RecvWR(sg=[recv_sge], num_sge=1, wr_id=i)
        test.server.mr.write(str(iterations - i - 1) * msg_size, msg_size, i * msg_size)
        test.server.qp.post_recv(recv_wr)

    for i in range(iterations):
        send_sge = SGE(test.client.mr.buf + (msg_size * i), msg_size, test.client.mr.lkey)
        send_wr = SendWR(opcode=opcode, num_sge=1, sg=[send_sge], wr_id=i)
        if opcode == e.IBV_WR_RDMA_WRITE_WITH_IMM:
            send_wr.imm_data = socket.htonl(i + iterations)
            imm_data_exp.append(i + iterations)
            send_wr.set_wr_rdma(int(test.client.rkey), int(test.client.raddr + i * msg_size))
        test.client.mr.write(str(i % 10) * msg_size, msg_size, i * msg_size)
        test.client.qp.post_send(send_wr)

    send_id_order = poll_cq_ex(test.client.cq, iterations)
    recv_id_order = poll_cq_ex(test.server.cq, iterations, data=imm_data_exp)
    # With opcodes that don't consume Recv WQEs (e.g. WRITE and WRITE_WITH_IMM) the buffer
    # scattering offsets are defined by the sender.
    recv_id_order = send_id_order if opcode == e.IBV_WR_RDMA_WRITE_WITH_IMM else recv_id_order

    for i, j in zip(recv_id_order, send_id_order):
        exp_buff = bytearray((str(j % 10) * msg_size), 'utf-8')
        recv_buff = test.server.mr.read(msg_size, i * msg_size)
        if recv_buff != exp_buff:
            raise PyverbsRDMAError(f'Data validation failed: expected {exp_buff},'
                                   f' received {recv_buff}')


def traffic(client, server, iters, gid_idx, port, is_cq_ex=False, send_op=e.IBV_WR_SEND,
            new_send=False, force_page_faults=False):
    """
    Runs basic traffic between two sides
    :param client: client side, clients base class is BaseTraffic
    :param server: server side, servers base class is BaseTraffic
    :param iters: number of traffic iterations
    :param gid_idx: local gid index
    :param port: IB port
    :param is_cq_ex: If True, use poll_cq_ex() rather than poll_cq()
    :param send_op: The send_wr opcode.
    :param new_send: If True use new post send API.
    :param force_page_faults: If True, use madvise to hint that we don't need the MR's buffer to
                              force page faults (useful for ODP testing).
    :return:
    """
    if is_datagram_qp(client):
        ah_client = get_global_ah(client, gid_idx, port)
        ah_server = get_global_ah(server, gid_idx, port)
    else:
        ah_client = None
        ah_server = None
    poll = poll_cq_ex if is_cq_ex else poll_cq

    imm_data = None
    if send_op in [e.IBV_WR_SEND_WITH_IMM, e.IBV_WR_RDMA_WRITE_WITH_IMM]:
        imm_data = IMM_DATA

    s_recv_wr = get_recv_wr(server)
    c_recv_wr = get_recv_wr(client)
    for qp_idx in range(server.qp_count):
        # prepare the receive queue with RecvWR
        post_recv(client, c_recv_wr, qp_idx=qp_idx)
        post_recv(server, s_recv_wr, qp_idx=qp_idx)
    read_offset = GRH_SIZE if client.qp.qp_type == e.IBV_QPT_UD else 0
    for _ in range(iters):
        for qp_idx in range(server.qp_count):
            if force_page_faults:
                madvise(client.mr.buf, client.msg_size)
                madvise(server.mr.buf, server.msg_size)
            c_send_wr, c_sg = get_send_elements(client, False, send_op)
            if client.use_mr_prefetch:
                flags = e._IBV_ADVISE_MR_FLAG_FLUSH
                if client.use_mr_prefetch == 'async':
                    flags = 0
                prefetch_mrs(client, [c_sg], advice=client.prefetch_advice,
                             flags=flags)
            c_send_object = c_sg if new_send else c_send_wr
            send(client, c_send_object, send_op, new_send, qp_idx,
                 ah_client, is_imm=(imm_data != None))
            poll(client.cq)
            poll(server.cq, data=imm_data)
            post_recv(server, s_recv_wr, qp_idx=qp_idx)
            msg_received_list = get_msg_received(server, read_offset)
            for msg in msg_received_list:
                validate(msg, True, server.msg_size)
            s_send_wr, s_sg = get_send_elements(server, True, send_op)
            if server.use_mr_prefetch:
                flags = e._IBV_ADVISE_MR_FLAG_FLUSH
                if server.use_mr_prefetch == 'async':
                    flags = 0
                prefetch_mrs(server, [s_sg], advice=server.prefetch_advice,
                             flags=flags)
            s_send_object = s_sg if new_send else s_send_wr
            send(server, s_send_object, send_op, new_send, qp_idx,
                 ah_server, is_imm=(imm_data != None))
            poll(server.cq)
            poll(client.cq, data=imm_data)
            post_recv(client, c_recv_wr, qp_idx=qp_idx)
            msg_received_list = get_msg_received(client,read_offset)
            for msg in msg_received_list:
                validate(msg, False, server.msg_size)


def get_msg_received(agr_obj, read_offset):
    msg_received_list = [agr_obj.mr.read(agr_obj.msg_size, read_offset)]
    if hasattr(agr_obj, 'use_mixed_mr') and agr_obj.use_mixed_mr:
        msg_received_list.append(agr_obj.non_odp_mr.read(agr_obj.msg_size, read_offset))
    return msg_received_list


def gen_ethernet_header(dst_mac=PacketConsts.DST_MAC, src_mac=PacketConsts.SRC_MAC,
                        ether_type=PacketConsts.ETHER_TYPE_IPV4):
    """
    Generates Ethernet header using the values from the PacketConst class by default.
    :param dst_mac: Destination mac address
    :param src_mac: Source mac address
    :param ether_type: Ether type of next header
    :return: Ethernet header
    """
    header = struct.pack('!6s6s',
                        bytes.fromhex(dst_mac.replace(':', '')),
                        bytes.fromhex(src_mac.replace(':', '')))
    header += ether_type.to_bytes(2, 'big')
    return header


def gen_ipv4_header(packet_len, next_proto=socket.IPPROTO_UDP, src_ip=PacketConsts.SRC_IP,
                    dst_ip=PacketConsts.DST_IP):
    """
    Generates IPv4 header using the values from the PacketConst class by default.
    :param packet_len: Length of all fields following the IP header
    :param next_proto: protocol type of next header
    :param src_ip: Source mac address
    :param dst_ip: Destination mac address
    :return: IPv4 header
    """
    ip_total_len = packet_len + PacketConsts.IPV4_HEADER_SIZE
    return struct.pack('!2B3H2BH4s4s', (PacketConsts.IP_V4 << 4) +
                       PacketConsts.IHL, 0, ip_total_len, 0,
                       PacketConsts.IP_V4_FLAGS << 13,
                       PacketConsts.TTL_HOP_LIMIT, next_proto, 0,
                       socket.inet_aton(src_ip),
                       socket.inet_aton(dst_ip))


def gen_udp_header(packet_len, src_port=PacketConsts.SRC_PORT, dst_port=PacketConsts.DST_PORT):
    """
    Generates UDP header using the values from the PacketConst class by default.
    :param packet_len: Length of all fields following the UDP header
    :param src_port: Source port
    :param dst_port: Destination port
    :return: UDP header
    """
    udp_total_len = packet_len + PacketConsts.UDP_HEADER_SIZE
    return struct.pack('!4H', src_port, dst_port, udp_total_len, 0)


def gen_gre_header(ether_type=PacketConsts.ETHER_TYPE_IPV4):
    """
    Generates GRE header using the values from the PacketConst class by default.
    :param ether_type: Ether type of tunneled next header
    :return: GRE header
    """
    return struct.pack('!2BHI', PacketConsts.GRE_FLAGS << 4, PacketConsts.GRE_VER,
                       ether_type, PacketConsts.GRE_KEY)


def gen_vxlan_header():
    """
    Generates VXLAN header using the values from the PacketConst class by default.
    :return: VXLAN header
    """
    return struct.pack('!II', PacketConsts.VXLAN_FLAGS << 24, PacketConsts.VXLAN_VNI << 8)


def gen_geneve_header(vni=PacketConsts.GENEVE_VNI, oam=PacketConsts.GENEVE_OAM,
                      proto=PacketConsts.ETHER_TYPE_ETH):
    """
    Generates Geneve header using the values from the PacketConst class by default.
    :param vni: geneve vni
    :param oam: geneve oam
    :param proto: Ether type of next header inside the tunnel
    :return: Geneve header
    """
    return struct.pack('!BBHL', (0 << 6) + 0, (oam << 7) + (0 << 6) + 0, proto, (vni << 8) + 0)

def gen_bth_header(opcode=PacketConsts.BTH_OPCODE, dst_qp=PacketConsts.BTH_DST_QP, a=PacketConsts.BTH_A):
    """
    Generates ROCE BTH header using the values from the PacketConst class by default.
    :param opcode: BTH opcode
    :param dst_qp: BTH dst QP
    :param a: BTH acknowledgment bit
    :return: ROCE BTH header
    """
    return struct.pack('!2BH2BH2L', opcode, 0, PacketConsts.BTH_PARTITION_KEY,
                       PacketConsts.BTH_BECN << 6, dst_qp >> 16, dst_qp & 0xffff, a << 31, 0)


def gen_packet(msg_size, l3=PacketConsts.IP_V4, l4=PacketConsts.UDP_PROTO, with_vlan=False, **kwargs):
    """
    Generates a Eth | IPv4 or IPv6 | UDP or TCP packet with hardcoded values in
    the headers and randomized payload.
    :param msg_size: total packet size
    :param l3: Packet layer 3 type: 4 for IPv4 or 6 for IPv6
    :param l4: Packet layer 4 type: 'tcp' or 'udp'
    :param with_vlan: if True add VLAN header to the packet
    :param kwargs: Arguments:
            * *src_mac*
                Source MAC address to use in the packet.
            * *src_ipv4*
                Source IPv4 address to use in the packet.
    :return: packet
    """
    l3_header_size = getattr(PacketConsts, f'IPV{str(l3)}_HEADER_SIZE')
    l4_header_size = getattr(PacketConsts, f'{l4.upper()}_HEADER_SIZE')
    payload_size = max(0, msg_size - l3_header_size - l4_header_size -
                       PacketConsts.ETHER_HEADER_SIZE)
    next_hdr = getattr(socket, f'IPPROTO_{l4.upper()}')
    ip_total_len = msg_size - PacketConsts.ETHER_HEADER_SIZE

    # Ethernet header
    src_mac = kwargs.get('src_mac', bytes.fromhex(PacketConsts.SRC_MAC.replace(':', '')))
    packet = struct.pack('!6s6s',
                         bytes.fromhex(PacketConsts.DST_MAC.replace(':', '')), src_mac)
    if with_vlan:
        packet += struct.pack('!HH', PacketConsts.VLAN_TPID, (PacketConsts.VLAN_PRIO << 13) +
                              (PacketConsts.VLAN_CFI << 12) + PacketConsts.VLAN_ID)
        payload_size -= PacketConsts.VLAN_HEADER_SIZE
        ip_total_len -= PacketConsts.VLAN_HEADER_SIZE

    if l3 == PacketConsts.IP_V4:
        packet += PacketConsts.ETHER_TYPE_IPV4.to_bytes(2, 'big')
    else:
        packet += PacketConsts.ETHER_TYPE_IPV6.to_bytes(2, 'big')

    if l3 == PacketConsts.IP_V4:
        # IPv4 header
        src_ipv4 = kwargs.get('src_ipv4', PacketConsts.SRC_IP)
        packet += struct.pack('!2B3H2BH4s4s', (PacketConsts.IP_V4 << 4) +
                              PacketConsts.IHL, 0, ip_total_len, 0,
                              PacketConsts.IP_V4_FLAGS << 13,
                              PacketConsts.TTL_HOP_LIMIT, next_hdr, 0,
                              socket.inet_aton(src_ipv4),
                              socket.inet_aton(PacketConsts.DST_IP))
    else:
        # IPv6 header
        packet += struct.pack('!IH2B16s16s', (PacketConsts.IP_V6 << 28),
                       ip_total_len, next_hdr, PacketConsts.TTL_HOP_LIMIT,
                       socket.inet_pton(socket.AF_INET6, PacketConsts.SRC_IP6),
                       socket.inet_pton(socket.AF_INET6, PacketConsts.DST_IP6))

    if l4 == PacketConsts.UDP_PROTO:
        # UDP header
        packet += struct.pack('!4H', PacketConsts.SRC_PORT,
                              PacketConsts.DST_PORT,
                              payload_size + PacketConsts.UDP_HEADER_SIZE, 0)
    else:
        # TCP header
        packet += struct.pack('!2H2I4H', PacketConsts.SRC_PORT,
                              PacketConsts.DST_PORT, 0, 0,
                              PacketConsts.TCP_HEADER_SIZE_WORDS << 12,
                              PacketConsts.WINDOW_SIZE, 0, 0)
    # Payload
    packet += str.encode('a' * payload_size)
    return packet


def get_send_elements_raw_qp(agr_obj, l3=PacketConsts.IP_V4,
                             l4=PacketConsts.UDP_PROTO, with_vlan=False,
                             packet_to_send=None, **packet_args):
    """
    Creates a single SGE and a single Send WR for agr_obj's RAW QP type. The
    content of the message is Eth | Ipv4 | UDP packet.
    :param agr_obj: Aggregation object which contains all resources necessary
    :param l3: Packet layer 3 type: 4 for IPv4 or 6 for IPv6
    :param l4: Packet layer 4 type: 'tcp' or 'udp'
    :param with_vlan: if True add VLAN header to the packet
    :param packet_to_send: If passed, the other packet related parameters would
                           be ignored, and this will be the packet to send.
    :param packet_args: Pass packet_args to gen_packets method.
    :return: send wr, its SGE, and message
    """
    mr = agr_obj.mr
    msg = packet_to_send if packet_to_send is not None else \
        gen_packet(agr_obj.msg_size, l3, l4, with_vlan, **packet_args)
    mr.write(msg, agr_obj.msg_size)
    sge = SGE(mr.buf, agr_obj.msg_size, mr.lkey)
    send_wr = SendWR(opcode=e.IBV_WR_SEND, num_sge=1, sg=[sge])
    return send_wr, sge, msg


def validate_raw(msg_received, msg_expected, skip_idxs):
    size = len(msg_expected)
    for i in range(size):
        if (msg_received[i] != msg_expected[i]) and i not in skip_idxs:
            err_msg = f'Data validation failure:\nexpected {msg_expected}\n\nreceived {msg_received}'
            raise PyverbsError(err_msg)


def sampler_traffic(client, server, iters, l3=PacketConsts.IP_V4, l4=PacketConsts.UDP_PROTO):
    """
    Send raw ethernet traffic
    :param client: client side, clients base class is BaseTraffic
    :param server: server side, servers base class is BaseTraffic
    :param iters: number of traffic iterations
    :param l3: Packet layer 3 type: 4 for IPv4 or 6 for IPv6
    :param l4: Packet layer 4 type: 'tcp' or 'udp'
    """
    s_recv_wr = get_recv_wr(server)
    c_recv_wr = get_recv_wr(client)
    for qp_idx in range(server.qp_count):
        # Prepare the receive queue with RecvWR
        post_recv(client, c_recv_wr, qp_idx=qp_idx)
        post_recv(server, s_recv_wr, qp_idx=qp_idx)
    poll = poll_cq_ex if isinstance(client.cq, CQEX) else poll_cq
    for _ in range(iters):
        for qp_idx in range(server.qp_count):
            c_send_wr, c_sg, msg = get_send_elements_raw_qp(client, l3, l4, False)
            send(client, c_send_wr, e.IBV_WR_SEND, False, qp_idx)
            poll(client.cq)


def raw_traffic(client, server, iters, l3=PacketConsts.IP_V4,
                l4=PacketConsts.UDP_PROTO, with_vlan=False, expected_packet=None,
                skip_idxs=None, packet_to_send=None):
    """
    Runs raw ethernet traffic between two sides
    :param client: client side, clients base class is BaseTraffic
    :param server: server side, servers base class is BaseTraffic
    :param iters: number of traffic iterations
    :param l3: Packet layer 3 type: 4 for IPv4 or 6 for IPv6
    :param l4: Packet layer 4 type: 'tcp' or 'udp'
    :param with_vlan: if True add VLAN header to the packet
    :param expected_packet: Expected packet for validation (when different from
                            the originally sent).
    :param skip_idxs: indexes to skip during packet validation
    :param packet_to_send: If passed, the other packet related parameters would
                           be ignored, and this will be the packet to send.
    """
    skip_idxs = [] if skip_idxs is None else skip_idxs
    s_recv_wr = get_recv_wr(server)
    c_recv_wr = get_recv_wr(client)
    for qp_idx in range(server.qp_count):
        # prepare the receive queue with RecvWR
        post_recv(client, c_recv_wr, qp_idx=qp_idx)
        post_recv(server, s_recv_wr, qp_idx=qp_idx)
    read_offset = 0
    poll = poll_cq_ex if isinstance(client.cq, CQEX) else poll_cq
    for _ in range(iters):
        for qp_idx in range(server.qp_count):
            c_send_wr, c_sg, msg = get_send_elements_raw_qp(client, l3, l4, with_vlan,
                                                            packet_to_send=packet_to_send)
            send(client, c_send_wr, e.IBV_WR_SEND, False, qp_idx)
            poll(client.cq)
            poll(server.cq)
            post_recv(server, s_recv_wr, qp_idx=qp_idx)
            msg_received = server.mr.read(server.msg_size, read_offset)
            # Validate received packet
            validate_raw(msg_received,
                         expected_packet if expected_packet else msg, skip_idxs)


def raw_rss_traffic(client, server, iters, l3=PacketConsts.IP_V4,
                    l4=PacketConsts.UDP_PROTO, with_vlan=False, num_packets=1):
    """
    Runs raw ethernet rss traffic between two sides.
    :param client: client side, clients base class is BaseTraffic
    :param server: server side, servers base class is BaseTraffic
    :param iters: number of traffic iterations
    :param l3: Packet layer 3 type: 4 for IPv4 or 6 for IPv6
    :param l4: Packet layer 4 type: 'tcp' or 'udp'
    :param with_vlan: if True add VLAN header to the packet
    :param num_packets: Number of packets to send with different ipv4 src
                        address in each iteration.
    :return: None
    """
    s_recv_wr = get_recv_wr(server)
    for qp_idx in range(server.qp_count):
        # prepare the receive queue with RecvWR
        post_recv(server, s_recv_wr, qp_idx=qp_idx, num_wqes=num_packets)
    for _ in range(iters):
        for qp_idx in range(server.qp_count):
            for i in range(num_packets):
                c_send_wr, c_sg, msg = get_send_elements_raw_qp(
                    client, l3, l4, with_vlan,
                    src_ipv4='.'.join([str(num) for num in range(i, i + 4)]))
                send(client, c_send_wr, e.IBV_WR_SEND, False, qp_idx)
                poll_cq(client.cq)
            completions = 0
            start_poll_t = time.perf_counter()
            while completions < num_packets and \
                    (time.perf_counter() - start_poll_t < POLL_CQ_TIMEOUT):
                for cq in server.cqs:
                    n, wcs = cq.poll()
                    if n > 0:
                        if wcs[0].status != e.IBV_WC_SUCCESS:
                            raise PyverbsRDMAError(
                                f'Completion status is {wc_status_to_str(wcs[0].status)}',
                                wcs[0].status)
                        completions += 1
                        if completions >= num_packets:
                            break
            if completions < num_packets:
                raise PyverbsError(f'Expected {num_packets} completions - got {completions}')
            post_recv(server, s_recv_wr, qp_idx=qp_idx, num_wqes=num_packets)


def flush_traffic(client, server, iters, gid_idx, port, new_send=False,
                  send_op=None):
    """
    Runs basic RDMA FLUSH traffic that client requests a FLUSH to server.
    Simply, run RDMA WRITE and then follow up by a RDMA FLUSH.
    No receive WQEs are posted.
    :param client: client side, clients base class is BaseTraffic
    :param server: server side, servers base class is BaseTraffic
    :param iters: number of traffic iterations
    :param gid_idx: local gid index
    :param port: IB port
    :param new_send: If True use new post send API.
    :param send_op: The send_wr opcode.
    :return:
    """
    rdma_traffic(client, server, iters, gid_idx, port, new_send, e.IBV_WR_RDMA_WRITE)
    for i in range(iters):
        if client.level == e.IBV_FLUSH_MR:
            client.msg_size = 0 if i == 0 else random.randint(0, 12345678)
        send(client, None, send_op, new_send)
        wcs = _poll_cq(client.cq)
        if (wcs[0].status != e.IBV_WC_SUCCESS):
            break
    return wcs


def prepare_validate_data(client=None, server=None):
    if server:
        server.mem_write('s' * server.msg_size, server.msg_size)
    if client:
        client.mem_write('c' * client.msg_size, client.msg_size)


def rdma_traffic(client, server, iters, gid_idx, port, new_send=False,
                 send_op=None, force_page_faults=False):
    """
    Runs basic RDMA traffic between two sides. No receive WQEs are posted. For
    RDMA send with immediate, use traffic().
    :param client: client side, clients base class is BaseTraffic
    :param server: server side, servers base class is BaseTraffic
    :param iters: number of traffic iterations
    :param gid_idx: local gid index
    :param port: IB port
    :param new_send: If True use new post send API.
    :param send_op: The send_wr opcode.
    :param force_page_faults: If True, use madvise to hint that we don't need the MR's buffer to
                              force page faults (useful for ODP testing).
    :return:
    """
    # Using the new post send API, we need the SGE, not the SendWR
    if isinstance(client, Mlx5DcResources) or \
       isinstance(client, SRDResources):
        ah_client = get_global_ah(client, gid_idx, port)
        ah_server = get_global_ah(server, gid_idx, port)
    else:
        ah_client = None
        ah_server = None
    send_element_idx = 1 if new_send else 0
    same_side_check =  send_op in [e.IBV_WR_RDMA_READ,
                                   e.IBV_WR_ATOMIC_CMP_AND_SWP,
                                   e.IBV_WR_ATOMIC_FETCH_AND_ADD]
    for _ in range(iters):
        if force_page_faults:
            madvise(client.mr.buf, client.msg_size)
            madvise(server.mr.buf, server.msg_size)
        prepare_validate_data(client=client, server=server)
        c_send_wr = get_send_elements(client, False, send_op)[send_element_idx]
        send(client, c_send_wr, send_op, new_send, ah=ah_client)
        poll_cq(client.cq)
        if same_side_check:
            msg_received = client.mem_read(client.msg_size)
        else:
            msg_received = server.mem_read(server.msg_size)
        validate(msg_received, False if same_side_check else True,
                 server.msg_size)
        s_send_wr = get_send_elements(server, True, send_op)[send_element_idx]
        prepare_validate_data(client=client, server=server)
        send(server, s_send_wr, send_op, new_send, ah=ah_server)
        poll_cq(server.cq)
        if same_side_check:
            msg_received = server.mem_read(client.msg_size)
        else:
            msg_received = client.mem_read(server.msg_size)
        validate(msg_received, True if same_side_check else False,
                 client.msg_size)


def atomic_traffic(client, server, iters, gid_idx, port, new_send=False,
                   send_op=None, receiver_val=1, sender_val=2, swap=0,
                   client_wr=1, server_wr=1, **kwargs):
    """
    Runs atomic traffic between two sides.
    :param client: Client side, clients base class is BaseTraffic
    :param server: Server side, servers base class is BaseTraffic
    :param iters: Number of traffic iterations
    :param gid_idx: Local gid index
    :param port: IB port
    :param new_send: If True use new post send API.
    :param send_op: The send_wr opcode.
    :param receiver_val: The requested value on the reciver MR.
    :param sender_val: The requested value on the sender SendWR.
    :param client_wr: Number of WR the client will post before polling all of them
    :param server_wr: Number of WR the server will post before polling all of them
    :param kwargs: General arguments (shared with other traffic functions).
    """
    send_element_idx = 1 if new_send else 0
    if is_datagram_qp(client):
        ah_client = get_global_ah(client, gid_idx, port)
        ah_server = get_global_ah(server, gid_idx, port)
    else:
        ah_client = None
        ah_server = None

    for _ in range(iters):
        client.mr.write(int.to_bytes(sender_val, 1, byteorder='big') * 8, 8)
        server.mr.write(int.to_bytes(receiver_val, 1, byteorder='big') * 8, 8)
        for _ in range(client_wr):
            c_send_wr = get_atomic_send_elements(client,
                                                 send_op,
                                                 cmp_add=sender_val,
                                                 swap=swap)[send_element_idx]
            if isinstance(server, XRCResources):
                c_send_wr.set_qp_type_xrc(server.srq.get_srq_num())
            send(client, c_send_wr, send_op, new_send, ah=ah_client,
                 cmp_add=sender_val, swap=swap)
        poll_cq(client.cq, count=client_wr)
        validate_atomic(send_op, server, client,
                        receiver_val=receiver_val + sender_val * (client_wr - 1),
                        send_cmp_add=sender_val, send_swp=swap)
        server.mr.write(int.to_bytes(sender_val, 1, byteorder='big') * 8, 8)
        client.mr.write(int.to_bytes(receiver_val, 1, byteorder='big') * 8, 8)
        for _ in range(server_wr):
            s_send_wr = get_atomic_send_elements(server,
                                                 send_op,
                                                 cmp_add=sender_val,
                                                 swap=swap)[send_element_idx]
            if isinstance(client, XRCResources):
                s_send_wr.set_qp_type_xrc(client.srq.get_srq_num())
            send(server, s_send_wr, send_op, new_send, ah=ah_server,
                 cmp_add=sender_val, swap=swap)
        poll_cq(server.cq, count=server_wr)
        validate_atomic(send_op, client, server,
                        receiver_val=receiver_val + sender_val * (server_wr - 1),
                        send_cmp_add=sender_val, send_swp=swap)


def validate_atomic(opcode, recv_player, send_player, receiver_val,
                    send_cmp_add, send_swp):
    """
    Validate the data after atomic operations. The expected data in each side of
    traffic depends on the atomic type and the sender SendWR values.
    :param opcode: The atomic opcode.
    :param recv_player: The receiver player.
    :param send_player: The sender player.
    :param receiver_val: The value on the receiver MR before the atomic action.
    :param send_cmp_add: The send WR compare/add value depende on the atomic
                         type.
    :param send_swp: The send WR swap value, used only in atomic compare and
                     swap.
    """
    send_expected = receiver_val
    if opcode in [e.IBV_WR_ATOMIC_CMP_AND_SWP,
                  e.IBV_QP_EX_WITH_ATOMIC_CMP_AND_SWP]:
        recv_expected = send_swp if receiver_val == send_cmp_add \
            else receiver_val
    if opcode in [e.IBV_WR_ATOMIC_FETCH_AND_ADD,
                  e.IBV_QP_EX_WITH_ATOMIC_FETCH_AND_ADD]:
        recv_expected = receiver_val + send_cmp_add
    send_actual = int.from_bytes(send_player.mr.read(length=8, offset=0),
                                 byteorder='big')
    recv_actual = int.from_bytes(recv_player.mr.read(length=8, offset=0),
                                 byteorder='big')
    if send_actual != int8b_from_int(send_expected):
        raise PyverbsError(
            'Atomic sender data validation failed: expected {exp}, received {rcv}'.
                format(exp=int8b_from_int(send_expected), rcv=send_actual))
    if recv_actual != int8b_from_int(recv_expected):
        raise PyverbsError(
            'Atomic reciver data validation failed: expected {exp}, received {rcv}'.
                format(exp=int8b_from_int(recv_expected), rcv=recv_actual))


def int8b_from_int(num):
    """
    Duplicate one-byte value int to 8 bytes.
    e.g. 1 => b'\x01\x01\x01\x01\x01\x01\x01\x01' == 72340172838076673
    :param num: One byte int number (0 <= num < 256).
    :return: The new number in int format.
    """
    num_multi_8_str = int.to_bytes(num, 1, byteorder='big') * 8
    return int.from_bytes(num_multi_8_str, byteorder='big')


def get_atomic_send_elements(agr_obj, opcode, cmp_add=0, swap=0):
    """
    Creates a single SGE and a single Send WR for atomic operations.
    :param agr_obj: Aggregation object which contains all resources necessary
    :param opcode: The send opcode
    :param cmp_add: The compare or add value (depends on the opcode).
    :param swap: The swap value.
    :return: Send WR and its SGE
    """
    sge = SGE(agr_obj.mr.buf, 8, agr_obj.mr_lkey)
    send_wr = SendWR(opcode=opcode, num_sge=1, sg=[sge])
    send_wr.set_wr_atomic(rkey=int(agr_obj.rkey), addr=int(agr_obj.raddr),
                          compare_add=int8b_from_int(cmp_add),
                          swap=int8b_from_int(swap))
    return send_wr, sge


def xrc_traffic(client, server, is_cq_ex=False, send_op=None, force_page_faults=False):
    """
    Runs basic xrc traffic, this function assumes that number of QPs, which
    server and client have are equal, server.send_qp[i] is connected to
    client.recv_qp[i], each time server.send_qp[i] sends a message, it is
    redirected to client.srq because client.recv_qp[i] and client.srq are
    under the same xrcd. The traffic flow in the opposite direction is the same.
    :param client: Aggregation object of the active side, should be an instance
    of XRCResources class
    :param server: Aggregation object of the passive side, should be an instance
    of XRCResources class
    :param is_cq_ex: If True, use poll_cq_ex() rather than poll_cq()
    :param send_op: If not None, new post send API is assumed.
    :param force_page_faults: If True, use madvise to hint that we don't need the MR's buffer to
                              force page faults (useful for ODP testing).
    :return: None
    """
    poll = poll_cq_ex if is_cq_ex else poll_cq
    server.remote_srqn = client.srq.get_srq_num()
    client.remote_srqn = server.srq.get_srq_num()
    s_recv_wr = get_recv_wr(server)
    c_recv_wr = get_recv_wr(client)
    post_recv(client, c_recv_wr, num_wqes=client.qp_count*client.num_msgs)
    post_recv(server, s_recv_wr, num_wqes=server.qp_count*server.num_msgs)
    # Using the new post send API, we need the SGE, not the SendWR
    send_element_idx = 1 if send_op else 0
    for _ in range(client.num_msgs):
        for i in range(server.qp_count):
            if force_page_faults:
                madvise(client.mr.buf, client.msg_size)
                madvise(server.mr.buf, server.msg_size)
            c_send_wr = get_send_elements(client, False)[send_element_idx]
            if send_op is None:
                c_send_wr.set_qp_type_xrc(client.remote_srqn)
            xrc_post_send(client, i, c_send_wr, send_op)
            poll(client.cq)
            poll(server.cq)
            msg_received = server.mr.read(server.msg_size, 0)
            validate(msg_received, True, server.msg_size)
            s_send_wr = get_send_elements(server, True)[send_element_idx]
            if send_op is None:
                s_send_wr.set_qp_type_xrc(server.remote_srqn)
            xrc_post_send(server, i, s_send_wr, send_op)
            poll(server.cq)
            poll(client.cq)
            msg_received = client.mr.read(client.msg_size, 0)
            validate(msg_received, False, client.msg_size)


# Decorators
def requires_odp(qp_type, required_odp_caps):
    def outer(func):
        def inner(instance):
            ctx = getattr(instance, 'ctx', d.Context(name=instance.dev_name))
            odp_supported(ctx, qp_type, required_odp_caps)
            if getattr(instance, 'is_implicit', False):
                odp_implicit_supported(instance.ctx)
            return func(instance)
        return inner
    return outer


def requires_root_on_eth(port_num=1):
    def outer(func):
        def inner(instance):
            if not (is_eth(instance.ctx, port_num) and is_root()):
                raise unittest.SkipTest('Must be run by root on Ethernet link layer')
            return func(instance)
        return inner
    return outer


def requires_mcast_support():
    """
    Check if the device support multicast
    return: True if multicast is supported
    """
    def outer(func):
        def inner(instance):
            ctx = d.Context(name=instance.dev_name)
            if ctx.query_device().max_mcast_grp == 0:
                raise unittest.SkipTest('Multicast is not supported on this device')
            return func(instance)
        return inner
    return outer


def odp_supported(ctx, qp_type, required_odp_caps):
    """
    Check device ODP capabilities
    :param ctx: Device Context
    :param qp_type: QP type ('rc', 'ud' or 'uc')
    :param required_odp_caps: ODP Capability mask of specified device
    :return: None
    """
    odp_caps = ctx.query_device_ex().odp_caps
    if odp_caps.general_caps == 0:
        raise unittest.SkipTest('ODP is not supported - No ODP caps')
    qp_odp_caps = getattr(odp_caps, '{}_odp_caps'.format(qp_type))
    if required_odp_caps & qp_odp_caps != required_odp_caps:
        raise unittest.SkipTest('ODP is unavailable - Operation not supported on this device')


def odp_implicit_supported(ctx):
    """
    Check device ODP implicit capability.
    :param ctx: Device Context
    :return: None
    """
    odp_caps = ctx.query_device_ex().odp_caps
    has_odp_implicit = odp_caps.general_caps & e.IBV_ODP_SUPPORT_IMPLICIT
    if has_odp_implicit == 0:
        raise unittest.SkipTest('ODP implicit is not supported')


def odp_v2_supported(ctx):
    """
    ODPv2 check
    :return: True/False if ODPv2 supported
    """
    from tests.mlx5_prm_structs import QueryHcaCapIn, QueryOdpCapOut, DevxOps, QueryHcaCapMod
    query_cap_in = QueryHcaCapIn(op_mod=DevxOps.MLX5_CMD_OP_QUERY_ODP_CAP << 1 | \
                                        QueryHcaCapMod.CURRENT)
    cmd_res = ctx.devx_general_cmd(query_cap_in, len(QueryOdpCapOut()))
    query_cap_out = QueryOdpCapOut(cmd_res)
    if query_cap_out.status:
        raise PyverbsRDMAError(f'QUERY_HCA_CAP has failed with status ({query_cap_out.status}) '
                               f'and syndrome ({query_cap_out.syndrome})')
    return query_cap_out.capability.mem_page_fault == 1


def requires_odpv2(func):
    def inner(instance):
        if not odp_v2_supported(instance.ctx):
            raise unittest.SkipTest('ODPv2 is not supported')
        return func(instance)
    return inner


def get_pci_name(dev_name):
    pci_name = glob.glob(f'/sys/bus/pci/devices/*/infiniband/{dev_name}')
    if not pci_name:
        raise unittest.SkipTest(f'Could not find the PCI device of {dev_name}')
    return pci_name[0].split('/')[5]


def requires_eswitch_on(func):
    def inner(instance):
        if not (is_eth(d.Context(name=instance.dev_name), instance.ib_port)
                and eswitch_mode_check(instance.dev_name)):
            raise unittest.SkipTest('Must be run on Ethernet link layer with Eswitch on')
        return func(instance)
    return inner


def eswitch_mode_check(dev_name):
    pci_name = get_pci_name(dev_name)
    eswicth_off_msg = f'Device {dev_name} must be in switchdev mode'
    try:
        cmd_out = subprocess.check_output(['devlink', 'dev', 'eswitch', 'show', f'pci/{pci_name}'],
                                          stderr=subprocess.DEVNULL)
        if 'switchdev' not in str(cmd_out):
            raise unittest.SkipTest(eswicth_off_msg)
    except subprocess.CalledProcessError:
        raise unittest.SkipTest(eswicth_off_msg)
    return True


def requires_roce_disabled(func):
    def inner(instance):
        if is_roce_enabled(instance.dev_name):
            raise unittest.SkipTest('ROCE must be disabled')
        return func(instance)
    return inner


def is_roce_enabled(dev_name):
    pci_name = get_pci_name(dev_name)
    cmd_out = subprocess.check_output(['devlink', 'dev', 'param', 'show', f'pci/{pci_name}',
                                       'name', 'enable_roce'],
                                      stderr=subprocess.DEVNULL)
    if 'value true' in str(cmd_out):
        return True
    return False


def requires_encap_disabled_if_eswitch_on(func):
    def inner(instance):
        if not (is_eth(d.Context(name=instance.dev_name), instance.ib_port)
                and encap_mode_check(instance.dev_name)):
            raise unittest.SkipTest('Encap must be disabled when Eswitch on')
        return func(instance)
    return inner


def encap_mode_check(dev_name):
    pci_name = get_pci_name(dev_name)
    encap_enable_msg = f'Device {dev_name}: Encap must be disabled over switchdev mode'
    try:
        cmd_out = subprocess.check_output(['devlink', 'dev', 'eswitch', 'show', f'pci/{pci_name}'],
                                          stderr=subprocess.DEVNULL)
        if 'switchdev' in str(cmd_out):
            if any([i for i in ['encap enable', 'encap-mode basic'] if i in str(cmd_out)]):
                raise unittest.SkipTest(encap_enable_msg)
    except subprocess.CalledProcessError:
        raise unittest.SkipTest(encap_enable_msg)
    return True

def requires_huge_pages():
    def outer(func):
        def inner(instance):
            huge_pages_supported()
            return func(instance)
        return inner
    return outer


def skip_unsupported(func):
    def func_wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except PyverbsRDMAError as ex:
            if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]:
                raise unittest.SkipTest(f'Operation not supported ({str(ex)})')
            raise ex
    return func_wrapper


def huge_pages_supported():
    """
    Check if huge pages are supported in the kernel.
    :return: None
    """
    huge_path = '/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages'
    if not os.path.isfile(huge_path):
        raise unittest.SkipTest('Huge pages of size 2M is not supported in this platform')
    with open(huge_path, 'r') as f:
        if not int(f.read()):
            raise unittest.SkipTest('There are no huge pages of size 2M allocated')


@skip_unsupported
def query_nic_flow_table_caps(instance):
    from tests.mlx5_prm_structs import QueryHcaCapIn, QueryQosCapOut, QueryHcaCapOp, \
        QueryHcaCapMod, QueryCmdHcaNicFlowTableCapOut
    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
    query_cap_in = QueryHcaCapIn(op_mod=(QueryHcaCapOp.HCA_NIC_FLOW_TABLE_CAP << 0x1) | \
                                        QueryHcaCapMod.CURRENT)
    cmd_res = ctx.devx_general_cmd(query_cap_in, len(QueryQosCapOut()))
    query_cap_out = QueryCmdHcaNicFlowTableCapOut(cmd_res)
    if query_cap_out.status:
        raise PyverbsRDMAError(f'QUERY_HCA_CAP has failed with status ({query_cap_out.status}) '
                               f'and syndrome ({query_cap_out.syndrome})')
    return query_cap_out.capability


def prefetch_mrs(agr_obj, sg_list, advice=e._IBV_ADVISE_MR_ADVICE_PREFETCH_WRITE,
                 flags=e._IBV_ADVISE_MR_FLAG_FLUSH):
    """
    Pre-fetch a range of an on-demand paging MR.
    :param agr_obj: Aggregation object which contains all resources necessary
    :param sg_list: SGE list
    :param advice: The requested advice value
    :param flags: Describes the properties of the advice operation
    :return: None
    """
    try:
        agr_obj.pd.advise_mr(advice, flags, sg_list)
    except PyverbsRDMAError as ex:
        if ex.error_code == errno.EOPNOTSUPP:
            raise unittest.SkipTest(f'Advise MR with flags ({flags}) and advice ({advice}) is not supported')
        raise ex


def is_eth(ctx, port_num):
    """
    Querires the device's context's <port_num> port for its link layer.
    :param ctx: The Context to query
    :param port_num: Which Context's port to query
    :return: True if the port's link layer is Ethernet, else False
    """
    return ctx.query_port(port_num).link_layer == e.IBV_LINK_LAYER_ETHERNET


def is_datagram_qp(agr_obj):
    if agr_obj.qp.qp_type == e.IBV_QPT_UD or \
       isinstance(agr_obj, SRDResources) or \
       isinstance(agr_obj, Mlx5DcResources):
        return True
    return False


def is_root():
    return os.geteuid() == 0


def post_rq_state_bad_flow(test_obj):
    """
    Check post_recive on rq while qp is in invalid state.
    - Change qp's state to IBV_QPS_RESET
    - Verify post receive on qp fails
    :param test_obj: An instance of RDMATestCase
    :return: None.
    """
    qp_attr = QPAttr(qp_state=e.IBV_QPS_RESET, cur_qp_state=e.IBV_QPS_RTS)
    test_obj.server.qps[0].modify(qp_attr, e.IBV_QP_STATE)
    recv_wr = get_recv_wr(test_obj.server)
    with test_obj.assertRaises(PyverbsRDMAError) as ex:
        post_recv(test_obj.server, recv_wr, qp_idx=0)
    test_obj.assertEqual(ex.exception.error_code, errno.EINVAL)


def post_sq_state_bad_flow(test_obj):
    """
    Check post_send on sq while qp is in invalid state.
    - Change qp's state to IBV_QPS_RESET
    - Verify post send on qp fails
    :param test_obj: An instance of RDMATestCase
    :return: None.
    """
    qp_idx = 0
    qp_attr = QPAttr(qp_state=e.IBV_QPS_RESET, cur_qp_state=e.IBV_QPS_RTS)
    test_obj.client.qps[qp_idx].modify(qp_attr, e.IBV_QP_STATE)
    ah = get_global_ah(test_obj.client, test_obj.gid_index, test_obj.ib_port)
    _, sg = get_send_elements(test_obj.client, False)
    with test_obj.assertRaises(PyverbsRDMAError) as ex:
        send(test_obj.client, sg, e.IBV_WR_SEND, new_send=True,
             qp_idx=qp_idx, ah=ah)
    test_obj.assertEqual(ex.exception.error_code, errno.EINVAL)


def full_rq_bad_flow(test_obj):
    """
    Check post_recive while qp's rq is full.
    - Find qp's rq length.
    - Fill the qp with work requests until overflow.
    :param test_obj: An instance of RDMATestCase
    :return: None.
    """
    qp_attr, _ = test_obj.server.qps[0].query(e.IBV_QP_CAP)
    max_recv_wr = qp_attr.cap.max_recv_wr
    with test_obj.assertRaises(PyverbsRDMAError) as ex:
        for _ in range (max_recv_wr + 1):
            s_recv_wr = get_recv_wr(test_obj.server)
            post_recv(test_obj.server, s_recv_wr, qp_idx=0)
    test_obj.assertEqual(ex.exception.error_code, errno.ENOMEM)


def create_rq_with_larger_sgl_bad_flow(test_obj):
    """
    Check post_receive on qp while wr sgl is bigger than
    max sge allowed for the qp
    - Find max sge allowed for the qp
    - Create wr with sgl bigger than the max
    - Verify post receive on qp fails
    :param test_obj: An instance of RDMATestCase
    :return: None.
    """
    qp_idx = 0
    server_mr = test_obj.server.mr
    server_mr_buf = server_mr.buf
    qp_attr, _ = test_obj.server.qps[qp_idx].query(e.IBV_QP_CAP)
    max_recv_sge = qp_attr.cap.max_recv_sge
    length = test_obj.server.msg_size // (max_recv_sge + 1)
    sgl = []
    offset = 0
    for _ in range(max_recv_sge + 1):
        sgl.append(SGE(server_mr_buf + offset, length, server_mr.lkey))
        offset = offset + length
    s_recv_wr = RecvWR(sg=sgl, num_sge=max_recv_sge + 1)
    with test_obj.assertRaises(PyverbsRDMAError) as ex:
        post_recv(test_obj.server, s_recv_wr, qp_idx=qp_idx)
    test_obj.assertEqual(ex.exception.error_code, errno.EINVAL)


def high_rate_send(agr_obj, packet, rate_limit, timeout=2):
    """
    Sends packet at high rate for 'timeout' seconds.
    :param agr_obj: Aggregation object which contains all resources necessary
    :param packet: Packet to send
    :param rate_limit: Minimal rate limit in MBps
    :param timeout: Seconds to send the packets
    """
    send_sg = SGE(agr_obj.mr.buf, len(packet), agr_obj.mr.lkey)
    agr_obj.mr.write(packet, len(packet))
    send_wr = SendWR(num_sge=1, sg=[send_sg])
    poll = poll_cq_ex if isinstance(agr_obj.cq, CQEX) else poll_cq
    iterations = 0
    start_send_t = time.perf_counter()
    while (time.perf_counter() - start_send_t) < timeout:
        agr_obj.qp.post_send(send_wr)
        poll(agr_obj.cq)
        iterations += 1
    # Calculate the rate
    rate = agr_obj.msg_size * iterations / timeout / 1000000
    assert rate > rate_limit, 'Traffic rate is smaller than minimal rate for the test'


def get_pkey_from_kernel(device, port=1, index=0):
    path = f'/sys/class/infiniband/{device}/ports/{port}/pkeys/{index}'
    output = subprocess.check_output(['cat', path], universal_newlines=True)
    pkey_hex = output.strip()
    pkey_decimal = int(pkey_hex, 16)
    return pkey_decimal
