#This patch was developed both in-house and from outside. We plan to submit it
#upstream, but do not yet have a target date for doing so
#
# HG changeset patch
# User Boris.Chiu@Oracle.COM
# Parent 6f1b3e12e65a05883b7375d196cad71d6e5ce1bc
PSARC 2012/384 Fast IB node death detection
16037511 Add support SM events to facilitate fast node death detection (userland
diff -r 6f1b3e12e65a examples/asyncwatch.c
--- a/examples/asyncwatch.c Tue Nov 24 20:12:48 2015 -0800
+++ b/examples/asyncwatch.c Tue Nov 24 20:13:37 2015 -0800
@@ -35,11 +35,72 @@
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <signal.h>
+#include <string.h>
+#include <strings.h>
+#if !(defined(__SVR4) && defined(__sun))
#include <endian.h>
#include <byteswap.h>
+#endif
#include <infiniband/verbs.h>
+#define IS_PORT_EVENT(event) \
+ ((event == IBV_EVENT_PORT_ACTIVE) || \
+ (event == IBV_EVENT_PORT_ERR ) || \
+ (event == IBV_EVENT_LID_CHANGE) || \
+ (event == IBV_EVENT_PKEY_CHANGE) || \
+ (event == IBV_EVENT_SM_CHANGE) || \
+ (event == IBV_EVENT_GID_CHANGE) || \
+ (event == IBV_EVENT_CLIENT_REREGISTER))
+
+#define IS_SM_EVENT(event) \
+ ((event == IBV_EVENT_MCG_CREATED) || \
+ (event == IBV_EVENT_MCG_DELETED) || \
+ (event == IBV_EVENT_GID_AVAIL) || \
+ (event == IBV_EVENT_GID_UNAVAIL))
+
+#define IS_QP_EVENT(event) \
+ ((event == IBV_EVENT_CQ_ERR) || \
+ (event == IBV_EVENT_QP_FATAL) || \
+ (event == IBV_EVENT_QP_REQ_ERR) || \
+ (event == IBV_EVENT_COMM_EST) || \
+ (event == IBV_EVENT_SQ_DRAINED) || \
+ (event == IBV_EVENT_PATH_MIG) || \
+ (event == IBV_EVENT_PATH_MIG_ERR) || \
+ (event == IBV_EVENT_QP_LAST_WQE_REACHED) || \
+ (event == IBV_EVENT_QP_ACCESS_ERR))
+
+#define IS_CQ_EVENT(event) \
+ (event == IBV_EVENT_CQ_ERR)
+
+#define IS_SRQ_EVENT(event) \
+ ((event == IBV_EVENT_SRQ_ERR) || \
+ (event == IBV_EVENT_SRQ_LIMIT_REACHED))
+
+#define IS_CA_EVENT(event) \
+ (event == IBV_EVENT_DEVICE_FATAL)
+
+
+struct ibv_device **dev_list;
+struct ibv_context *context;
+struct ibv_async_event event;
+union ibv_gid *gids = NULL;
+uint_t num_gids = 0;
+ibv_sm_event_type_t events;
+
+static struct option long_options[] = {
+ {"sm", 0, 0, 's'},
+ {"GUID", 0, 0, 'G'},
+ {"MCG", 0, 0, 'M'},
+ {"port", 1, 0, 'p'},
+ {0, 0, 0, 0}
+};
+
+
static const char *event_name_str(enum ibv_event_type event_type)
{
switch (event_type) {
@@ -59,7 +120,14 @@
return "IBV_EVENT_CLIENT_REREGISTER";
case IBV_EVENT_GID_CHANGE:
return "IBV_EVENT_GID_CHANGE";
-
+ case IBV_EVENT_MCG_CREATED:
+ return "IBV_EVENT_MCG_CREATED";
+ case IBV_EVENT_MCG_DELETED:
+ return "IBV_EVENT_MCG_DELETED";
+ case IBV_EVENT_GID_AVAIL:
+ return "IBV_EVENT_GID_AVAIL";
+ case IBV_EVENT_GID_UNAVAIL:
+ return "IBV_EVENT_GID_UNAVAIL";
case IBV_EVENT_CQ_ERR:
case IBV_EVENT_QP_FATAL:
case IBV_EVENT_QP_REQ_ERR:
@@ -76,14 +144,172 @@
}
}
+static void catch_signal(int sig_num)
+{
+ ibv_unregister_sm_events(context, events, num_gids, gids);
+ if (gids)
+ free(gids);
+ ibv_close_device(context);
+ (void) ibv_free_device_list(dev_list);
+ exit (0);
+}
+
+static void usage(const char *argv0)
+{
+ printf("Usage:\n");
+ printf("\n");
+ printf("Options:\n");
+ printf("[ -s, --sm<gid> ]\t\tsm event\n");
+ printf("[ -M, --M ]\t\t\tsm event for MGID (multicast)\n");
+ printf("[ -G, --G ]\t\t\tsm event for UGID (unicast)\n");
+ printf("[ -p, --port=<port> ]\t\t(default 1)\n");
+ printf("\nExamples;\n");
+ printf("ibv_asyncwatch -s\t\t# monitor event=IBV_SM_EVENT_ALL\n");
+ printf("ibv_asyncwatch -G -s\t\t# monitor event="
+ "IBV_SM_EVENT_UGID_ALL\n");
+ printf("ibv_asyncwatch -M -s\t\t# monitor event="
+ "IBV_SM_EVENT_MGID_ALL\n");
+ printf("ibv_asyncwatch -G -s0x0021280001a0e4d9,0x0021280001a0e4da\n");
+ printf("\t\t\t\t# monitor event=IBV_SM_EVENT_UGID\n");
+ printf("ibv_asyncwatch -M -s0xff12:4001:ffff::c:2238,");
+ printf("0xff12:ffff::38:220c\n");
+ printf("\t\t\t\t# monitor event=IBV_SM_EVENT_MGID\n");
+}
+
+
+uint_t get_gids(char *argptr, uint64_t subnet_prefix)
+{
+ char *curr, *next;
+ char *guid_str_p1, *guid_str_p2 = NULL;
+ int i = 0;
+ int data_num;
+
+ for (curr = argptr; curr; curr = next, i++) {
+ next = strchr(curr, ',');
+ if (next)
+ next++;
+ }
+ data_num = i;
+ if (data_num == 0)
+ return (0);
+
+ gids = (union ibv_gid *)calloc(data_num, sizeof (union ibv_gid));
+ guid_str_p1 = malloc(strlen(argptr));
+ strncpy(guid_str_p1, argptr, strlen(argptr));
+
+ i = 0;
+ guid_str_p2 = strtok(guid_str_p1, (const char *)",");
+ while (guid_str_p2 != NULL) {
+ gids[i].global.subnet_prefix = subnet_prefix;
+ gids[i].global.interface_id =
+ htonll((uint64_t)strtoull(guid_str_p2, 0, 0));
+ i++;
+ guid_str_p2 = strtok(NULL, (const char *)",");
+ }
+ free (guid_str_p1);
+ return (data_num);
+}
+
+void process_one_mcg_gid(union ibv_gid *gid, char *mcg_str)
+{
+ char *token, *token_p, half_token[3];
+ uint8_t mcg_gid[16];
+ int i, j = 0, num_data = -1;
+ char *curr, *next;
+
+ /* find out how many two-byte data from command line input */
+ for (curr = mcg_str; curr; curr = next, num_data++) {
+ next = strchr(curr, ':');
+ if (next)
+ next++;
+ }
+
+ if (num_data > 8) {
+ fprintf(stderr, "Invalid MGID input format: %s\n", mcg_str);
+ exit (-1);
+ }
+
+ curr = mcg_str + 2; /* Skip past 0x */
+ while ((token = strsep(&curr, ":")) != NULL && j < 15) {
+ if (strncmp(token, "\0", 1) == 0) {
+ /* We have :: in the input */
+ for (i = 0; i < 8 - num_data; i++) {
+ mcg_gid[j++] = 0;
+ mcg_gid[j++] = 0;
+ }
+ } else {
+ if (strlen(token) < 3) {
+ mcg_gid[j++] = 0;
+ mcg_gid[j++] =
+ (uint8_t)strtoll(token, NULL, 16);
+ } else {
+ memset(half_token, 0, 3);
+ token_p = token;
+ if (strlen(token) == 3) {
+ strncpy(half_token, token, 1);
+ token_p += 1;
+ } else {
+ strncpy(half_token, token, 2);
+ token_p += 2;
+ }
+ mcg_gid[j++] = (uint8_t)strtol(half_token,
+ NULL, 16);
+
+ mcg_gid[j++] = (uint8_t)strtol(token_p,
+ NULL, 16);
+ }
+ }
+ }
+
+ memcpy(gid->raw, mcg_gid, 16);
+}
+
+uint_t get_mcgs(char *argptr, uint64_t subnet_prefix)
+{
+ char *curr, *next;
+ char *mcg_str_p1, *mcg_str_p2 = NULL;
+ int i = 0;
+ int data_num;
+
+ for (curr = argptr; curr; curr = next, i++) {
+ next = strchr(curr, ',');
+ if (next)
+ next++;
+ }
+ data_num = i;
+ if (data_num == 0)
+ return (0);
+
+ gids = (union ibv_gid *)calloc(data_num, sizeof (union ibv_gid));
+ mcg_str_p1 = malloc(strlen(argptr));
+ strncpy(mcg_str_p1, argptr, strlen(argptr));
+
+ i = 0;
+ mcg_str_p2 = strtok(mcg_str_p1, (const char *)",");
+ while (mcg_str_p2 != NULL) {
+ if (strncmp(mcg_str_p2, "0xff", 4) != 0) {
+ fprintf(stderr, "Invalid MGID input format: %s\n",
+ mcg_str_p2);
+ exit (-1);
+ }
+ process_one_mcg_gid(&gids[i], mcg_str_p2);
+ i++;
+ mcg_str_p2 = strtok(NULL, (const char *)",");
+ }
+ free(mcg_str_p1);
+ return (data_num);
+}
+
int main(int argc, char *argv[])
{
- struct ibv_device **dev_list;
- struct ibv_context *context;
- struct ibv_async_event event;
-
- /* Force line-buffering in case stdout is redirected */
- setvbuf(stdout, NULL, _IOLBF, 0);
+ int c;
+ int ret;
+ uint_t port = 1; /* default */
+ uint_t do_sm_event_register = 0;
+ union ibv_gid sgid;
+ uint64_t subnet_prefix = 0ULL;
+ int mcgflag = 0;
+ int guidflag = 0;
dev_list = ibv_get_device_list(NULL);
if (!dev_list) {
@@ -103,19 +329,111 @@
return 1;
}
- printf("%s: async event FD %d\n",
+ printf("\n%s: async event FD %d\n\n",
ibv_get_device_name(*dev_list), context->async_fd);
+ ibv_query_gid(context, port, 0, &sgid);
+ subnet_prefix = sgid.global.subnet_prefix;
+
+ while ((c = getopt_long(argc, argv, "p:GMs::t:", long_options, NULL))
+ != -1) {
+ switch(c) {
+ case 'G':
+ guidflag = 1;
+ break;
+ case 'M':
+ mcgflag = 1;
+ break;
+ case 's':
+ do_sm_event_register = 1;
+ if (mcgflag == 1)
+ num_gids =
+ get_mcgs(optarg, subnet_prefix);
+ else
+ num_gids =
+ get_gids(optarg, subnet_prefix);
+ break;
+ case 'p':
+ port = strtol(optarg, NULL, 0);
+ ibv_query_gid(context, port, 0, &sgid);
+ subnet_prefix = sgid.global.subnet_prefix;
+ break;
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ /* Force line-buffering in case stdout is redirected */
+ setvbuf(stdout, NULL, _IOLBF, 0);
+
+ if (num_gids) {
+ if (mcgflag)
+ events = IBV_SM_EVENT_MGID;
+ else
+ events = IBV_SM_EVENT_UGID;
+ } else {
+ if (mcgflag && guidflag)
+ events = IBV_SM_EVENT_ALL;
+ else if (mcgflag)
+ events = IBV_SM_EVENT_MGID_ALL;
+ else if (guidflag)
+ events = IBV_SM_EVENT_UGID_ALL;
+ else
+ events = IBV_SM_EVENT_ALL;
+ }
+
+ if (do_sm_event_register)
+ ret = ibv_register_sm_events(context, events, num_gids, gids);
+
+ (void) signal(SIGINT, catch_signal);
+
while (1) {
if (ibv_get_async_event(context, &event))
return 1;
- printf(" event_type %s (%d), port %d\n",
- event_name_str(event.event_type),
- event.event_type, event.element.port_num);
+ if (IS_PORT_EVENT(event.event_type))
+ printf("Event: %s (%d), port %d\n",
+ event_name_str(event.event_type),
+ event.event_type, event.element.port_num);
+ else if (IS_SM_EVENT(event.event_type))
+ printf("Event: %s (%d), gid " \
+ "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\
+ "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
+ event_name_str(event.event_type), event.event_type,
+ event.element.gid.raw[0], event.element.gid.raw[1],
+ event.element.gid.raw[2], event.element.gid.raw[3],
+ event.element.gid.raw[4], event.element.gid.raw[5],
+ event.element.gid.raw[6], event.element.gid.raw[7],
+ event.element.gid.raw[8], event.element.gid.raw[9],
+ event.element.gid.raw[10],
+ event.element.gid.raw[11],
+ event.element.gid.raw[12],
+ event.element.gid.raw[13],
+ event.element.gid.raw[14],
+ event.element.gid.raw[15]);
+ else if (IS_QP_EVENT(event.event_type))
+ printf("Event: %s (%d) QPN %d\n",
+ event_name_str(event.event_type), event.event_type,
+ event.element.qp->qp_num);
+ else if (IS_CQ_EVENT(event.event_type))
+ printf("Event: %s (%d) CQE %d\n",
+ event_name_str(event.event_type), event.event_type,
+ event.element.cq->cqe);
+ else if (IS_SRQ_EVENT(event.event_type))
+ printf("Event: %s (%d) SRQ %d\n",
+ event_name_str(event.event_type), event.event_type,
+ event.element.srq->handle);
+ else
+ printf("Event: %s (%d)\n",
+ event_name_str(event.event_type), event.event_type);
ibv_ack_async_event(&event);
+
+ if (event.event_type == IBV_EVENT_GID_AVAIL) {
+ ret = ibv_gid_reachable(context, port,
+ &event.element.gid, 0);
+ }
}
-
return 0;
}
diff -r 6f1b3e12e65a include/infiniband/kern-abi.h
--- a/include/infiniband/kern-abi.h Tue Nov 24 20:12:48 2015 -0800
+++ b/include/infiniband/kern-abi.h Tue Nov 24 20:13:37 2015 -0800
@@ -115,7 +115,10 @@
IB_USER_VERBS_CMD_SHARE_PD, /* =47 */
IB_USER_VERBS_CMD_REG_MR_RELAXED, /* =48 */
IB_USER_VERBS_CMD_DEREG_MR_RELAXED, /* =49 */
- IB_USER_VERBS_CMD_FLUSH_RELAXED_MR /* =50 */
+ IB_USER_VERBS_CMD_FLUSH_RELAXED_MR, /* =50 */
+ IB_USER_VERBS_CMD_REG_SM_EVENT,
+ IB_USER_VERBS_CMD_UNREG_SM_EVENT,
+ IB_USER_VERBS_CMD_GID_REACHABLE
};
#define IB_USER_VERBS_CMD_COMMAND_MASK 0xff
@@ -174,6 +177,8 @@
__u64 element;
__u32 event_type;
__u32 reserved;
+ __u64 subnet_prefix;
+ __u64 interface_id;
};
struct ibv_comp_event {
@@ -299,6 +304,34 @@
__u8 reserved[2];
};
+struct ibv_reg_sm_event {
+ __u32 command;
+ __u16 in_words;
+ __u16 out_words;
+ __u32 events;
+ __u32 data_num;
+ __u64 driver_data[0];
+};
+
+struct ibv_unreg_sm_event {
+ __u32 command;
+ __u16 in_words;
+ __u16 out_words;
+ __u32 events;
+ __u32 data_num;
+ __u64 driver_data[0];
+};
+
+struct ibv_gid_reachable {
+ __u32 command;
+ __u16 in_words;
+ __u16 out_words;
+ __u32 timeout;
+ __u8 port_num;
+ __u8 reserved[3];
+ __u8 gid[16];
+};
+
struct ibv_alloc_pd {
__u32 command;
__u16 in_words;
@@ -1104,7 +1137,10 @@
IB_USER_VERBS_CMD_SHARE_PD_V2 = -1,
IB_USER_VERBS_CMD_REG_MR_RELAXED_V2 = -1,
IB_USER_VERBS_CMD_DEREG_MR_RELAXED_V2 = -1,
- IB_USER_VERBS_CMD_FLUSH_RELAXED_MR_V2 = -1
+ IB_USER_VERBS_CMD_FLUSH_RELAXED_MR_V2 = -1,
+ IB_USER_VERBS_CMD_REG_SM_EVENT_V2 = -1,
+ IB_USER_VERBS_CMD_UNREG_SM_EVENT_V2 = -1,
+ IB_USER_VERBS_CMD_GID_REACHABLE_V2 = -1
};
struct ibv_modify_srq_v3 {
diff -r 6f1b3e12e65a include/infiniband/verbs.h
--- a/include/infiniband/verbs.h Tue Nov 24 20:12:48 2015 -0800
+++ b/include/infiniband/verbs.h Tue Nov 24 20:13:37 2015 -0800
@@ -239,6 +239,10 @@
IBV_EVENT_QP_LAST_WQE_REACHED,
IBV_EVENT_CLIENT_REREGISTER,
IBV_EVENT_GID_CHANGE,
+ IBV_EVENT_MCG_CREATED,
+ IBV_EVENT_MCG_DELETED,
+ IBV_EVENT_GID_AVAIL,
+ IBV_EVENT_GID_UNAVAIL,
};
struct ibv_async_event {
@@ -247,10 +251,20 @@
struct ibv_qp *qp;
struct ibv_srq *srq;
int port_num;
+ union ibv_gid gid;
} element;
enum ibv_event_type event_type;
};
+typedef enum ibv_sm_event_type_e {
+ IBV_SM_EVENT_MGID = 1,
+ IBV_SM_EVENT_MGID_ALL = 1 << 2,
+ IBV_SM_EVENT_UGID = 1 << 3,
+ IBV_SM_EVENT_UGID_ALL = 1 << 4,
+ IBV_SM_EVENT_ALL = 1 << 5
+
+} ibv_sm_event_type_t;
+
enum ibv_wc_status {
IBV_WC_SUCCESS,
IBV_WC_LOC_LEN_ERR,
@@ -1134,6 +1148,25 @@
int index, uint16_t *pkey);
/**
+ * ibv_register_sm_events - Register subnet event for GID change
+ */
+int ibv_register_sm_events(struct ibv_context *context,
+ ibv_sm_event_type_t event, uint_t gid_num, union ibv_gid *gids);
+
+/**
+ * ibv_unregister_sm_events - Unregister subnet event for GID change
+ */
+int ibv_unregister_sm_events(struct ibv_context *context,
+ ibv_sm_event_type_t event, uint_t gid_num, union ibv_gid *gids);
+
+/**
+ * ibv_gid_reachable - To contact subnet agent for GID status; reachable or
+ * not reachable
+ */
+int ibv_gid_reachable(struct ibv_context *context,
+ uint port, union ibv_gid *gid_p, int timeout);
+
+/**
* ibv_alloc_pd - Allocate a protection domain
*/
struct ibv_pd *ibv_alloc_pd(struct ibv_context *context);
diff -r 6f1b3e12e65a man/ibv_asyncwatch.1
--- a/man/ibv_asyncwatch.1 Tue Nov 24 20:12:48 2015 -0800
+++ b/man/ibv_asyncwatch.1 Tue Nov 24 20:13:37 2015 -0800
@@ -1,16 +1,78 @@
-.TH IBV_ASYNCWATCH 1 "August 30, 2005" "libibverbs" "USER COMMANDS"
+'\" te
+.TH IBV_ASYNCWATCH 1 "August 8, 2012" "libibverbs" "USER COMMANDS"
.SH NAME
ibv_asyncwatch \- display asynchronous events
.SH SYNOPSIS
-.B ibv_asyncwatch
-
+.sp
+.nf
+\fIibv_asyncwatch\fR [\-G | \-M] [\-s[<guid>]] [\-p port]
+\fIibv_asyncwactch\fR \-s
+\fIibv_asyncwatch\fR \-G \-s
+\fIibv_asyncwatch\fR \-M \-s
+\fIibv_asyncwatch\fR \-G [\-p port] \-s<guid1>,<guid2>,...
+\fIibv_asyncwatch\fR \-M [\-p port] \-s<mgid1>,<mgid2>,...
+.fi
+.sp
.SH DESCRIPTION
.PP
-Display asynchronous events forwarded to userspace for an RDMA device.
+Display asynchronous events forwarded to userspace for an InfiniBand device.
+SM events can be monitored using the '-s' option, which optionally
+takes a remote port GUID, or list of remote port GUIDS separated by ','.
+If '-s' is specified with no argument then all remote nodes reachable
+form device 0 are monitored, otherwise only the specified remote
+nodes are monitored. The following SM events are monitored using
+the '-s' option:
-.SH AUTHORS
-.TP
-Roland Dreier
-.RI < rolandd@cisco.com >
+ IBV_SM_EVENT_MCG_CREATED
+ An MCG specified by the "mgid" has been created
+ on this subnet.
+
+ IBV_SM_EVENT_MCG_DELETED
+ The MCG specified by the "mgid" has been deleted
+ on this subnet.
+
+ IBV_SM_EVENT_GID_AVAIL
+ The GID specified by the "guid" is available
+ on this subnet.
+
+ IBV_SM_EVENT_GID_UNAVAIL
+ The GID specified by the "guid" is no longer
+ available on this subnet.
+
+.SH OPTIONS
+.pp
+\-G Monitor SM event for Unicast GIDs
+.sp
+.pp
+\-M Monitor SM event for Multicast GIDs
+.pp
+\-s<GUID> Takes as an optional argument a comma separated list of remote port GUIDs if \-G is specified or Multicast GIDs if \-M is specified.
+.sp
+.PP
+\-p <port> use the specified ca_port.
+.sp
+.pp
+.SH EXAMPLES
+.PP
+To monitor event=IBV_SM_EVENT_ALL
+.sp
+ibv_asyncwatch -s
+.sp
+To monitor event=IBV_SM_EVENT_UGID_ALL
+.sp
+ibv_asyncwatch -G -s
+.sp
+To monitor event=IBV_SM_EVENT_MGID_ALL
+.sp
+ibv_asyncwatch -M -s
+.sp
+To monitor event=IBV_SM_EVENT_UGID
+.sp
+ibv_asyncwatch -G -s0x0021280001a0e4d9,0x0021280001a0e4da
+.sp
+To monitor event=IBV_SM_EVENT_MGID
+.sp
+ibv_asyncwatch -M -s0xff12:4001:ffff::c:2238
+.sp
diff -r 6f1b3e12e65a man/ibv_get_async_event.3
--- a/man/ibv_get_async_event.3 Tue Nov 24 20:12:48 2015 -0800
+++ b/man/ibv_get_async_event.3 Tue Nov 24 20:13:37 2015 -0800
@@ -14,7 +14,7 @@
.fi
.SH "DESCRIPTION"
.B ibv_get_async_event()
-waits for the next async event of the RDMA device context
+waits for the next async event of the InfiniBand device context
.I context
and returns it through the pointer
.I event\fR,
@@ -29,6 +29,8 @@
struct ibv_qp *qp; /* QP that got the event */
struct ibv_srq *srq; /* SRQ that got the event */
int port_num; /* port number that got the event */
+uint32_t xrc_qp_num; /* XRC QP that got the event */
+union ibv_gid gid; /* list of guids that got the event */
.in -8
} element;
enum ibv_event_type event_type; /* type of the event */
@@ -88,6 +90,16 @@
.TP
.B IBV_EVENT_DEVICE_FATAL \fR CA is in FATAL state
.PP
+.I Subnet events:
+.TP
+.B IBV_SM_EVENT_MCG_CREATED \fR notification of MCG creation
+.TP
+.B IBV_SM_EVENT_MCG_DELETED \fR notification of MCG deletion
+.TP
+.B IBV_SM_EVENT_GID_AVAIL \fR notification of GID available events
+.TP
+.B IBV_SM_EVENT_GID_UNAVAIL \fR notification of GID unavailable events
+.PP
.B ibv_ack_async_event()
acknowledge the async event
.I event\fR.
diff -r 6f1b3e12e65a src/device.c
--- a/src/device.c Tue Nov 24 20:12:48 2015 -0800
+++ b/src/device.c Tue Nov 24 20:13:37 2015 -0800
@@ -287,7 +287,15 @@
case IBV_EVENT_SRQ_LIMIT_REACHED:
event->element.srq = (void *) (uintptr_t) ev.element;
break;
-
+ case IBV_EVENT_GID_AVAIL:
+ case IBV_EVENT_GID_UNAVAIL:
+ case IBV_EVENT_MCG_CREATED:
+ case IBV_EVENT_MCG_DELETED:
+ event->element.gid.global.subnet_prefix
+ = ev.subnet_prefix;
+ event->element.gid.global.interface_id
+ = ev.interface_id;
+ break;
default:
event->element.port_num = ev.element;
break;
diff -r 6f1b3e12e65a src/enum_strs.c
--- a/src/enum_strs.c Tue Nov 24 20:12:48 2015 -0800
+++ b/src/enum_strs.c Tue Nov 24 20:13:37 2015 -0800
@@ -87,10 +87,14 @@
[IBV_EVENT_SRQ_LIMIT_REACHED] = "SRQ limit reached",
[IBV_EVENT_QP_LAST_WQE_REACHED] = "last WQE reached",
[IBV_EVENT_CLIENT_REREGISTER] = "client reregistration",
- [IBV_EVENT_GID_CHANGE] = "GID table change"
+ [IBV_EVENT_GID_CHANGE] = "GID table change",
+ [IBV_EVENT_MCG_CREATED] = "MCG created",
+ [IBV_EVENT_MCG_DELETED] = "MCG deleted",
+ [IBV_EVENT_GID_AVAIL] = "GID available",
+ [IBV_EVENT_GID_UNAVAIL] = "GID unavailable"
};
- if (event < IBV_EVENT_CQ_ERR || event > IBV_EVENT_GID_CHANGE)
+ if (event < IBV_EVENT_CQ_ERR || event > IBV_EVENT_GID_UNAVAIL)
return "unknown";
return event_type_str[event];
diff -r 6f1b3e12e65a src/libibverbs.map
--- a/src/libibverbs.map Tue Nov 24 20:12:48 2015 -0800
+++ b/src/libibverbs.map Tue Nov 24 20:13:37 2015 -0800
@@ -21,6 +21,9 @@
ibv_dereg_mr;
ibv_dereg_mr_relaxed;
ibv_flush_relaxed_mr;
+ ibv_register_sm_events;
+ ibv_unregister_sm_events;
+ ibv__gid_reachable;
ibv_create_comp_channel;
ibv_destroy_comp_channel;
ibv_create_cq;
diff -r 6f1b3e12e65a src/verbs.c
--- a/src/verbs.c Tue Nov 24 20:12:48 2015 -0800
+++ b/src/verbs.c Tue Nov 24 20:13:37 2015 -0800
@@ -49,6 +49,16 @@
#include "ibverbs.h"
+#define IBV_IS_VALID_UGID(gid) \
+ (gid->raw[0] != 0xff)
+
+#define IBV_IS_VALID_MGID(gid) \
+ ((gids->raw[0] == 0xff) && \
+ ((gids->raw[1] == 0x0e) || (gids->raw[1] == 0x02) || \
+ (gids->raw[1] == 0x05) || (gids->raw[1] == 0x08) || \
+ (gids->raw[1] == 0x1e) || (gids->raw[1] == 0x12) || \
+ (gids->raw[1] == 0x15) || (gids->raw[1] == 0x18)))
+
int ibv_rate_to_mult(enum ibv_rate rate)
{
switch (rate) {
@@ -203,6 +213,155 @@
}
default_symver(__ibv_query_pkey, ibv_query_pkey);
+int ibv_register_sm_events(struct ibv_context *context,
+ ibv_sm_event_type_t event, uint_t gid_num, union ibv_gid *gids)
+{
+ struct ibv_reg_sm_event *cmd;
+ int cmd_size, data_size;
+ void *data_p;
+
+ if (((gid_num > 0) && (gids == NULL)) ||
+ ((gid_num == 0) && (gids != NULL))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((event != IBV_SM_EVENT_UGID) && (event != IBV_SM_EVENT_UGID_ALL) &&
+ (event != IBV_SM_EVENT_MGID) && (event != IBV_SM_EVENT_MGID_ALL) &&
+ (event != IBV_SM_EVENT_ALL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (((event == IBV_SM_EVENT_UGID) || (event == IBV_SM_EVENT_MGID)) &&
+ (gid_num == 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (((event == IBV_SM_EVENT_UGID_ALL) ||
+ (event == IBV_SM_EVENT_MGID_ALL) || (event == IBV_SM_EVENT_ALL)) &&
+ (gid_num != 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ data_size = gid_num * (sizeof (union ibv_gid));
+ cmd_size = (sizeof (struct ibv_reg_sm_event)) + data_size;
+ data_p = (void *)gids;
+ cmd = alloca(cmd_size);
+ cmd->data_num = gid_num;
+
+ if ((event == IBV_SM_EVENT_UGID) && (!IBV_IS_VALID_UGID(gids))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((event == IBV_SM_EVENT_MGID) && (!IBV_IS_VALID_MGID(gids))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ IBV_INIT_CMD(cmd, cmd_size, REG_SM_EVENT);
+
+ cmd->events = event;
+ if (gid_num > 0)
+ memcpy(cmd->driver_data, data_p, data_size);
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (0);
+}
+
+int ibv_unregister_sm_events(struct ibv_context *context,
+ ibv_sm_event_type_t event, uint_t gid_num, union ibv_gid *gids)
+{
+ struct ibv_unreg_sm_event *cmd;
+ int cmd_size, data_size;
+ void *data_p;
+
+ if (((gid_num > 0) && (gids == NULL)) ||
+ ((gid_num == 0) && (gids != NULL))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((event != IBV_SM_EVENT_UGID) && (event != IBV_SM_EVENT_UGID_ALL) &&
+ (event != IBV_SM_EVENT_MGID) && (event != IBV_SM_EVENT_MGID_ALL) &&
+ (event != IBV_SM_EVENT_ALL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (((event == IBV_SM_EVENT_UGID) || (event == IBV_SM_EVENT_MGID)) &&
+ (gid_num == 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (((event == IBV_SM_EVENT_UGID_ALL) ||
+ (event == IBV_SM_EVENT_MGID_ALL) || (event == IBV_SM_EVENT_ALL)) &&
+ (gid_num != 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ data_size = gid_num*(sizeof (union ibv_gid));
+ cmd_size = (sizeof (struct ibv_unreg_sm_event)) + data_size;
+ data_p = (void *)gids;
+ cmd = alloca(cmd_size);
+ cmd->data_num = gid_num;
+
+ if ((event == IBV_SM_EVENT_UGID) && (!IBV_IS_VALID_UGID(gids))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((event == IBV_SM_EVENT_MGID) && (!IBV_IS_VALID_MGID(gids))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ IBV_INIT_CMD(cmd, cmd_size, UNREG_SM_EVENT);
+
+ cmd->events = event;
+ if (gid_num > 0)
+ memcpy(cmd->driver_data, data_p, data_size);
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (0);
+}
+
+int ibv_gid_reachable(struct ibv_context *context,
+ uint_t port, union ibv_gid *gid_p, int timeout)
+{
+ struct ibv_gid_reachable *cmd;
+ int rc;
+
+ cmd = alloca((sizeof (struct ibv_gid_reachable)));
+ cmd->port_num = port;
+ cmd->timeout = timeout;
+
+ IBV_INIT_CMD(cmd, sizeof (struct ibv_gid_reachable),
+ GID_REACHABLE);
+
+ memcpy(cmd->gid, gid_p, sizeof (*gid_p));
+
+ rc = write(context->cmd_fd, cmd, sizeof(struct ibv_gid_reachable));
+ if (rc < 0) {
+ return (-1);
+ }
+
+ return (0);
+}
+
struct ibv_pd *__ibv_alloc_pd(struct ibv_context *context)
{
struct ibv_pd *pd;