IBV_CREATE_CQ_EX(3)
π ibv_create_cq_ex π
okay so bestie, we're in the Libibverbs Programmer's Manual and today's main character is ibv_create_cq_ex(3) β the extended-verb way to spin up a completion queue. buckle up, it's giving very detailed and very slay. π
β¨ NAME β¨
ibv_create_cq_ex β create a completion queue (CQ) π¦
πΈ SYNOPSIS πΈ
#include <infiniband/verbs.h>
struct ibv_cq_ex *ibv_create_cq_ex(struct ibv_context *context,
struct ibv_cq_init_attr_ex *cq_attr);
π«Ά DESCRIPTION π«Ά
ibv_create_cq_ex() makes a completion queue (CQ) for the RDMA device context context. the cq_attr argument is a pointer to a struct ibv_cq_init_attr_ex, which is defined in <infiniband/verbs.h>. no cap, that header is where everything lives. π
struct ibv_cq_init_attr_ex {
int cqe; /* Minimum number of entries required for CQ */
void *cq_context; /* Consumer-supplied context returned for completion events */
struct ibv_comp_channel *channel; /* Completion channel where completion events will be queued. May be NULL if completion events will not be used. */
int comp_vector; /* Completion vector used to signal completion events. Must be >= 0 and < context->num_comp_vectors. */
uint64_t wc_flags; /* The wc_flags that should be returned in ibv_poll_cq_ex. Or'ed bit of enum ibv_wc_flags_ex. */
uint32_t comp_mask; /* compatibility mask (extended verb). */
uint32_t flags /* One or more flags from enum ibv_create_cq_attr_flags */
struct ibv_pd *parent_domain; /* Parent domain to be used by this CQ */
};
and here's the flag enum that wc_flags speaks, enum ibv_wc_flags_ex β it's literally a wishlist of what you want handed back in each work completion: π
enum ibv_wc_flags_ex {
IBV_WC_EX_WITH_BYTE_LEN = 1 << 0, /* Require byte len in WC */
IBV_WC_EX_WITH_IMM = 1 << 1, /* Require immediate in WC */
IBV_WC_EX_WITH_QP_NUM = 1 << 2, /* Require QP number in WC */
IBV_WC_EX_WITH_SRC_QP = 1 << 3, /* Require source QP in WC */
IBV_WC_EX_WITH_SLID = 1 << 4, /* Require slid in WC */
IBV_WC_EX_WITH_SL = 1 << 5, /* Require sl in WC */
IBV_WC_EX_WITH_DLID_PATH_BITS = 1 << 6, /* Require dlid path bits in WC */
IBV_WC_EX_WITH_COMPLETION_TIMESTAMP = 1 << 7, /* Require completion device timestamp in WC /*
IBV_WC_EX_WITH_CVLAN = 1 << 8, /* Require VLAN info in WC */
IBV_WC_EX_WITH_FLOW_TAG = 1 << 9, /* Require flow tag in WC */
IBV_WC_EX_WITH_COMPLETION_TIMESTAMP_WALLCLOCK = 1 << 11, /* Require completion wallclock timestamp in WC */
};
this next one, enum ibv_cq_init_attr_mask, is the compatibility-mask gang β it tells the driver which extra attr fields you're actually using: π
enum ibv_cq_init_attr_mask {
IBV_CQ_INIT_ATTR_MASK_FLAGS = 1 << 0,
IBV_CQ_INIT_ATTR_MASK_PD = 1 << 1,
};
and the flags themselves, enum ibv_create_cq_attr_flags β these are the lil behaviours you can turn on when you create the CQ: β
enum ibv_create_cq_attr_flags {
IBV_CREATE_CQ_ATTR_SINGLE_THREADED = 1 << 0, /* This CQ is used from a single threaded, thus no locking is required */
IBV_CREATE_CQ_ATTR_IGNORE_OVERRUN = 1 << 1, /* This CQ will not pass to error state if overrun, CQE always will be written to next entry.
* An application must be designed to avoid ever overflowing the CQ, otherwise CQEs might be lost.
*/
};
π Polling an extended CQ π
bestie, if you wanna poll an extended CQ efficiently, you'd use the following functions. iykyk. π
Completion iterator functions π§
int ibv_start_poll(struct ibv_cq_ex *cq, struct ibv_poll_cq_attr *attr)β start polling a batch of work completions. attr is given so this function can be easily extended in the future. it returns0on success or an error code otherwise. when there are no completions available on the CQ,ENOENTcomes back, but the CQ stays in a valid state β no drama. on success, you can query the completion's attributes with the query functions described below. if you got an error code,end_pollshouldn't be called.int ibv_next_poll(struct ibv_cq_ex *cq)β this one gets you the next work completion. it has to be called afterstart_polland beforeend_poll. returns0on success or an error code otherwise. when no completions are available on the CQ,ENOENTis returned, but the CQ remains valid. on success you can query the completion's attributes with the query functions below. if an error code comes back,end_pollshould still be called, indicating this is the end of the polled batch.void ibv_end_poll(struct ibv_cq_ex *cq)β this signals the end of the polling batch of work completions. after calling it, start a fresh batch by callingstart_pollagain. π₯
Polling fields in the completion πΈ
the members and functions below are how you poll the current completion. the current completion is whatever the iterator points at (start_poll and next_poll move that iterator along). heads up: you can only query fields you requested via wc_flags in ibv_create_cq_ex. also, some fields are only valid in certain opcodes and status codes. not every field is valid in every situation, and that's just the vibe. π
uint64_t wr_idβ can be accessed directly fromstruct ibv_cq_ex.enum ibv_wc_statusβ can be accessed directly fromstruct ibv_cq_ex.enum ibv_wc_opcode ibv_wc_read_opcode(struct ibv_cq_ex *cq);β get the opcode from the current completion.uint32_t ibv_wc_read_vendor_err(struct ibv_cq_ex *cq);β get the vendor error from the current completion.uint32_t ibv_wc_read_byte_len(struct ibv_cq_ex *cq);β get the payload length from the current completion.__be32 ibv_wc_read_imm_data(struct ibv_cq_ex *cq);β get the immediate data field from the current completion.uint32_t ibv_wc_read_invalidated_rkey(struct ibv_cq_ex *cq);β get the rkey invalidated by theSEND_INVALfrom the current completion.uint32_t ibv_wc_read_qp_num(struct ibv_cq_ex *cq);β get the QP number field from the current completion.uint32_t ibv_wc_read_src_qp(struct ibv_cq_ex *cq);β get the source QP number field from the current completion.unsigned int ibv_wc_read_wc_flags(struct ibv_cq_ex *cq);β get the QP flags field from the current completion.uint16_t ibv_wc_read_pkey_index(struct ibv_cq_ex *cq);β get the pkey index field from the current completion.uint32_t ibv_wc_read_slid(struct ibv_cq_ex *cq);β get the slid field from the current completion.uint8_t ibv_wc_read_sl(struct ibv_cq_ex *cq);β get the sl field from the current completion.uint8_t ibv_wc_read_dlid_path_bits(struct ibv_cq_ex *cq);β get the dlid_path_bits field from the current completion.uint64_t ibv_wc_read_completion_ts(struct ibv_cq_ex *cq);β get the completion timestamp from the current completion, in HCA clock units.uint64_t ibv_wc_read_completion_wallclock_ns(struct ibv_cq_ex *cq);β get the completion timestamp from the current completion and convert it from HCA clock units to wall clock nanoseconds. it's giving translation. β¨uint16_t ibv_wc_read_cvlan(struct ibv_cq_ex *cq);β get the CVLAN field from the current completion.uint32_t ibv_wc_read_flow_tag(struct ibv_cq_ex *cq);β get flow tag from the current completion.void ibv_wc_read_tm_info(struct ibv_cq_ex *cq, struct ibv_wc_tm_info *tm_info);β get tag matching info from the current completion.
struct ibv_wc_tm_info {
uint64_t tag; /* tag from TMH */
uint32_t priv; /* opaque user data from TMH */
};
π RETURN VALUE π
ibv_create_cq_ex() returns a pointer to the CQ, or NULL if the request fails. simple as that, bestie.
π NOTES π
ibv_create_cq_ex()may create a CQ with a size greater than or equal to the requested size. so check thecqeattribute in the returned CQ for the actual size β don't just assume you got exactly what you asked for. π- the CQ should be destroyed with
ibv_destroy_cq.
π SEE ALSO π
ibv_create_cq(3), ibv_destroy_cq(3), ibv_resize_cq(3), ibv_req_notify_cq(3), ibv_ack_cq_events(3), ibv_create_qp(3), ibv_alloc_parent_domain(3)
π AUTHORS π
Matan Barak <matanb@mellanox.com>
and that's the whole page, periodt. written by that Matan Barak icon, shipped as part of libibverbs, dated 2016-05-08. go forth and create your completion queues, bestie, you're gonna slay. ππβ¨
π¦ where this page comes from
- alpine 3.24: rdma-core-doc 61.0-r0 Β· GPL-2.0-only OR BSD-2-Clause
- centos-stream 10: rdma-core-devel 62.0-3.el10 Β· GPLv2 or BSD
- centos-stream 9: rdma-core-devel 61.0-3.el9 Β· GPLv2 or BSD
- centos-stream 9: rdma-core-devel 61.0-3.el9 Β· GPLv2 or BSD
- debian bookworm: libibverbs-dev 44.0-2 Β· BSD-MIT OR GPL-2.0-only
- debian trixie: libibverbs-dev 56.1-1 Β· BSD-MIT OR GPL-2.0-only
- fedora 43: rdma-core-devel 58.0-4.fc43 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 43: rdma-core-devel 58.0-4.fc43 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 44: rdma-core-devel 61.0-2.fc44 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 44: rdma-core-devel 61.0-2.fc44 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- nixos 26.05: rdma-core 62.0
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- ubuntu jammy: libibverbs-dev 39.0-1 Β· BSD-MIT OR GPL-2.0-only
- ubuntu noble: libibverbs-dev 50.0-2build2 Β· BSD-MIT OR GPL-2.0-only
- ubuntu noble: libibverbs-dev 50.0-2ubuntu0.2 Β· BSD-MIT OR GPL-2.0-only
- ubuntu questing: libibverbs-dev 56.1-1ubuntu1
- ubuntu resolute: libibverbs-dev 61.0-2ubuntu3 Β· BSD-MIT OR GPL-2.0-only
- ubuntu stonking: libibverbs-dev 64.0-1ubuntu1 Β· BSD-MIT OR GPL-2.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms