IBV_GET_ASYNC_EVENT(3)

πŸ’– ibv_get_async_event, ibv_ack_async_event β€” bestie's guide to grabbing & acking async events πŸ’–

okay so ✨ welcome to the Libibverbs Programmer's Manual, the corner of the docs where we talk about RDMA async events and honestly? it's giving main character energy. two functions, one vibe: ibv_get_async_event grabs an event, ibv_ack_async_event says "heard, ty bestie, we're done here." πŸ’…


✨ NAME ✨

ibv_get_async_event, ibv_ack_async_event β€” get or acknowledge asynchronous events πŸ¦‹


🌸 SYNOPSIS 🌸

#include <infiniband/verbs.h>

int ibv_get_async_event(struct ibv_context *context,
                        struct ibv_async_event *event);

void ibv_ack_async_event(struct ibv_async_event *event);

πŸŽ€ DESCRIPTION πŸŽ€

ibv_get_async_event() waits for the next async event of the RDMA device context context, and hands it back through the pointer event. That event is an ibv_async_event struct, and it's defined right there in <infiniband/verbs.h> β€” no cap, go look:

struct ibv_async_event {
        union {
                struct ibv_cq  *cq;             /* CQ that got the event */
                struct ibv_qp  *qp;             /* QP that got the event */
                struct ibv_srq *srq;            /* SRQ that got the event */
                struct ibv_wq  *wq;             /* WQ that got the event */
                int             port_num;       /* port number that got the event */
        } element;
        enum ibv_event_type     event_type;     /* type of the event */
};

here's the tea β˜•: only one member of that element union is actually valid at a time, and which one it is depends on the event_type member of the struct. so like, check event_type first, then go touch the union. iykyk.

event_type is gonna be one of the following events, and yes we're listing them ALL because they're all iconic in their own way:

πŸ‘‘ QP events

  • IBV_EVENT_QP_FATAL β€” bestie… an error occurred on a QP and it transitioned to error state 😭
  • IBV_EVENT_QP_REQ_ERR β€” Invalid Request Local Work Queue Error
  • IBV_EVENT_QP_ACCESS_ERR β€” Local access violation error πŸ’€
  • IBV_EVENT_COMM_EST β€” Communication was established on a QP ✨ (good news era)
  • IBV_EVENT_SQ_DRAINED β€” the Send Queue was drained of outstanding messages in progress
  • IBV_EVENT_PATH_MIG β€” a connection has migrated to the alternate path 🌈
  • IBV_EVENT_PATH_MIG_ERR β€” a connection failed to migrate to the alternate path πŸ™ˆ
  • IBV_EVENT_QP_LAST_WQE_REACHED β€” Last WQE Reached on a QP associated with an SRQ

πŸ’œ CQ events

  • IBV_EVENT_CQ_ERR β€” CQ is in error (CQ overrun) πŸ’€

🌸 SRQ events

  • IBV_EVENT_SRQ_ERR β€” an error occurred on an SRQ 😭
  • IBV_EVENT_SRQ_LIMIT_REACHED β€” the SRQ limit was reached

🧚 WQ events

  • IBV_EVENT_WQ_FATAL β€” an error occurred on a WQ and it transitioned to error state

⭐ Port events

  • IBV_EVENT_PORT_ACTIVE β€” Link became active on a port πŸ”₯
  • IBV_EVENT_PORT_ERR β€” Link became unavailable on a port 😭
  • IBV_EVENT_LID_CHANGE β€” LID was changed on a port
  • IBV_EVENT_PKEY_CHANGE β€” P_Key table was changed on a port
  • IBV_EVENT_SM_CHANGE β€” SM was changed on a port
  • IBV_EVENT_CLIENT_REREGISTER β€” SM sent a CLIENT_REREGISTER request to a port
  • IBV_EVENT_GID_CHANGE β€” GID table was changed on a port

🫢 CA events

  • IBV_EVENT_DEVICE_FATAL β€” CA is in FATAL state πŸ’€
  • IBV_EVENT_DEVICE_SPEED_CHANGE β€” speed changed on one or many ports of the device, due to configuration or state changes

and then ibv_ack_async_event() β€” it acknowledges the async event event. that's it, that's the whole job. queen behavior, minimal effort, maximum importance. πŸ‘‘


πŸ¦‹ RETURN VALUE πŸ¦‹

ibv_get_async_event() returns 0 on success, and -1 on error.

ibv_ack_async_event() returns no value. (it simply does not participate in the return value economy πŸ’…)


🌟 NOTES 🌟

⚠️ listen up, this one matters: ALL async events that ibv_get_async_event() returns must be acknowledged using ibv_ack_async_event(). every single one. no skipping. no "i'll do it later." the events are watching. πŸ‘€

and here's why that's not just a rule for the sake of rules: to avoid races, destroying an object (CQ, SRQ or QP) will wait for all affiliated events for that object to be acknowledged. this avoids a situation where an application retrieves an affiliated event after the corresponding object has already been destroyed. so like, the destroy call is literally sitting there waiting on you to ack. don't leave it on read. 😭

also important: ibv_get_async_event() is a blocking function. it blocks. it waits. it's patient. so if multiple threads call this function simultaneously, then when an async event occurs, only one thread will receive it β€” and ngl, it is not possible to predict which thread will receive it. mystery thread. chaos thread. nobody knows. πŸ™ˆ


✨ EXAMPLES ✨

okay so here's a code example that demonstrates one possible way to work with async events in non-blocking mode. it performs the following steps:

  1. Set the async events queue work mode to be non-blocked
  2. Poll the queue until it has an async event
  3. Get the async event and ack it

and here's the code, verbatim, because we do not freestyle code in this house:

/* change the blocking mode of the async event queue */
flags = fcntl(ctx->async_fd, F_GETFL);
rc = fcntl(ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
if (rc < 0) {
        fprintf(stderr, "Failed to change file descriptor of async event queue\n");
        return 1;
}

/*
 * poll the queue until it has an event and sleep ms_timeout
 * milliseconds between any iteration
 */
my_pollfd.fd      = ctx->async_fd;
my_pollfd.events  = POLLIN;
my_pollfd.revents = 0;

do {
        rc = poll(&my_pollfd, 1, ms_timeout);
} while (rc == 0);
if (rc < 0) {
        fprintf(stderr, "poll failed\n");
        return 1;
}

/* Get the async event */
if (ibv_get_async_event(ctx, &async_event)) {
        fprintf(stderr, "Failed to get async_event\n");
        return 1;
}

/* Ack the event */
ibv_ack_async_event(&async_event);

🌈 SEE ALSO 🌈


πŸ’– AUTHORS πŸ’–

Dotan Barak <dotanba@gmail.com>


and that's the whole page bestie!! 🫢 this libibverbs manual entry is dated 2006-10-31, brought to you by libibverbs, and honestly it's been serving reliable async-event knowledge since before most of us could read. stan. βœ¨πŸ’…πŸŽ€

πŸ“¦ where this page comes from