From 91ce18c6ec0b36bd1b9af5653c4dad6f75a2913a Mon Sep 17 00:00:00 2001 From: Annika Wierichs Date: Thu, 26 Oct 2017 15:04:47 +0200 Subject: [PATCH] Added a code generator, work in progress. Added ping pong for testing later. Added some more API calls. --- kernel/ibv.c | 126 +- .../function_prototypes.txt | 95 + tools/ibv_code_generator/ibv_gen.c | 1805 +++++++++++++++++ tools/ibv_code_generator/kernel_api.py | 121 ++ tools/ibv_code_generator/uhyve_handler.py | 0 tools/uhyve-ibv.h | 32 +- tools/uhyve.c | 58 +- usr/tests/CMakeLists.txt | 1 + usr/tests/ib/pingpong.c | 81 + usr/tests/ib/pingpong.h | 38 + usr/tests/ib/pingpong_ud.c | 861 ++++++++ usr/tests/ib_test.c | 4 +- 12 files changed, 3187 insertions(+), 35 deletions(-) create mode 100644 tools/ibv_code_generator/function_prototypes.txt create mode 100644 tools/ibv_code_generator/ibv_gen.c create mode 100755 tools/ibv_code_generator/kernel_api.py create mode 100644 tools/ibv_code_generator/uhyve_handler.py create mode 100644 usr/tests/ib/pingpong.c create mode 100644 usr/tests/ib/pingpong.h create mode 100644 usr/tests/ib/pingpong_ud.c diff --git a/kernel/ibv.c b/kernel/ibv.c index 89bb405a2..31d1cdae5 100644 --- a/kernel/ibv.c +++ b/kernel/ibv.c @@ -23,6 +23,9 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * TODO: Documentation + * */ @@ -38,16 +41,20 @@ // allocate the right amount of memory? #define MAX_NUM_OF_IBV_DEVICES 16 + typedef struct { - int *num_devices; + // Parameters: + int , *num_devices; + // Return value: struct ibv_device *dev_phys_ptr_list[MAX_NUM_OF_IBV_DEVICES]; // TODO: Can we make the return type struct ibv_device**? } __attribute__((packed)) uhyve_ibv_get_device_list_t; -struct ibv_device** h_ibv_get_device_list(int *num_devices) -{ +struct ibv_device** ibv_get_device_list(int *num_devices) { // num_devices can be mapped to physical memory right away. - uhyve_ibv_get_device_list_t uhyve_args = {(int*) virt_to_phys((size_t) num_devices)}; + uhyve_ibv_get_device_list_t uhyve_args = { + (int*) virt_to_phys((size_t) num_devices) + }; // Allocate memory for return value. struct ibv_device *devs = kmalloc(MAX_NUM_OF_IBV_DEVICES * sizeof(struct ibv_device)); @@ -65,6 +72,95 @@ struct ibv_device** h_ibv_get_device_list(int *num_devices) return list_virt; } + +const char* ibv_get_device_name(struct ibv_device *device) { + // TODO: Also forward this to uhyve for consistency? + return device->name; +} + + +typedef struct { + // Parameters: + struct ibv_device *device; + // Return value: + struct ibv_context *ret; +} __attribute__((packed)) uhyve_ibv_open_device_t; + +int ibv_open_device(struct ibv_device *device) { + uhyve_ibv_open_device_t uhyve_args = { + (struct ibv_device *) virt_to_phys((size_t) device), + }; + uhyve_args->ret = kmalloc(sizeof(struct ibv_context)); + + uhyve_send(UHYVE_PORT_IBV_OPEN_DEVICE, (unsigned)virt_to_phys((size_t) &uhyve_args)); + + // Set all pointers contained in returned data structure to valid kernel space addresses. + uhyve_args->ret->device = device; + + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context *context; + // Return value: + struct ibv_comp_channel *ret; +} __attribute__((packed)) uhyve_ibv_create_comp_channel_t; + +struct ibv_comp_channel* ibv_create_comp_channel(struct ibv_context *context) { + uhyve_ibv_create_comp_channel_t uhyve_args = { + (struct ibv_context *) virt_to_phys((size_t) context), + }; + uhyve_args->ret = kmalloc(sizeof(struct ibv_comp_channel)); + + uhyve_send(UHYVE_PORT_IBV_CREATE_COMP_CHANNEL, (unsigned)virt_to_phys((size_t) &uhyve_args)); + + // Set all pointers contained in returned data structure to valid kernel space addresses. + uhyve_args->ret->device = device; // todo + + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp *qp; + struct ibv_qp_attr *attr; + int attr_mask; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_modify_qp_t; + +int ibv_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, int attr_mask) { + uhyve_ibv_modify_qp_t uhyve_args = { + (struct ibv_qp *) virt_to_phys((size_t) qp), + (struct ibv_qp_attr *) virt_to_phys((size_t) attr), + attr_mask, + -1 + }; + uhyve_send(UHYVE_PORT_IBV_MODIFY_QP, (unsigned)virt_to_phys((size_t) &uhyve_args)); + return uhyve_args.ret; +} + +typedef struct { + // Parameters: + struct ibv_pd *pd; + struct ibv_ah_attr *attr; + // Return value: + struct ibv_ah *ret; +} __attribute__((packed)) uhyve_ibv_create_ah_t; + +struct ibv_ah* ibv_create_ah(struct ibv_pd *pd,struct ibv_ah_attr *attr) { + uhyve_ibv_create_ah_t uhyve_args = { + (struct ibv_pd *) virt_to_phys((size_t) pd), + (struct ibv_ah_attr *) virt_to_phys((size_t) attr), + }; + uhyve_send(UHYVE_PORT_IBV_CREATE_AH, (unsigned)virt_to_phys((size_t) &uhyve_args)); + return uhyve_args.ret; +} + + /*struct ibv_device** h_ibv_get_device_list(int *num_devices)*/ /*{*/ /*struct ibv_device *devs = calloc(MAX_NUM_OF_IBV_DEVICES, sizeof(struct ibv_device));*/ @@ -85,25 +181,3 @@ struct ibv_device** h_ibv_get_device_list(int *num_devices) /*uhyve_send(UHYVE_PORT_IBV_GET_DEVICE_LIST, (unsigned)virt_to_phys((size_t)&uhyve_args));*/ /*return list_virt;*/ /*}*/ - -/*void h_ibv_get_device_list(int *num_devices)*/ -/*{*/ - /*uhyve_ibv_get_device_list_t uhyve_args = {(int*) virt_to_phys((size_t) num_devices)};*/ - /*uhyve_args.first_device = (struct ibv_device*) virt_to_phys((size_t) uhyve_args.devices);*/ - /*[>&uhyve_args.devices = (struct ibv_device*) virt_to_phys((size_t) uhyve_args.devices);<]*/ - - /*uhyve_send(UHYVE_PORT_IBV_GET_DEVICE_LIST, (unsigned)virt_to_phys((size_t)&uhyve_args));*/ -/*}*/ - - -typedef struct { - struct ibv_device *device; - char *ret; -} __attribute__((packed)) uhyve_ibv_get_device_name_t; - -const char* h_ibv_get_device_name(struct ibv_device *device) -{ - uhyve_ibv_get_device_name_t uhyve_args = {(struct ibv_device*) virt_to_phys((size_t) device)}; - uhyve_send(UHYVE_PORT_IBV_GET_DEVICE_NAME, (unsigned)virt_to_phys((size_t)&uhyve_args)); - return uhyve_args.ret; -} diff --git a/tools/ibv_code_generator/function_prototypes.txt b/tools/ibv_code_generator/function_prototypes.txt new file mode 100644 index 000000000..b57d7c34e --- /dev/null +++ b/tools/ibv_code_generator/function_prototypes.txt @@ -0,0 +1,95 @@ +const char * ibv_wc_status_str(enum ibv_wc_status status) +int ibv_rate_to_mult(enum ibv_rate rate) +enum ibv_rate mult_to_ibv_rate(int mult) +int ibv_rate_to_mbps(enum ibv_rate rate) +enum ibv_rate mbps_to_ibv_rate(int mbps) +struct ibv_cq * ibv_cq_ex_to_cq(struct ibv_cq_ex * cq) +int ibv_start_poll(struct ibv_cq_ex * cq,struct ibv_poll_cq_attr * attr) +int ibv_next_poll(struct ibv_cq_ex * cq) +void ibv_end_poll(struct ibv_cq_ex * cq) +enum ibv_wc_opcode ibv_wc_read_opcode(struct ibv_cq_ex * cq) +uint32_t ibv_wc_read_vendor_err(struct ibv_cq_ex * cq) +uint32_t ibv_wc_read_byte_len(struct ibv_cq_ex * cq) +__be32 ibv_wc_read_imm_data(struct ibv_cq_ex * cq) +uint32_t ibv_wc_read_invalidated_rkey(struct ibv_cq_ex * cq) +uint32_t ibv_wc_read_qp_num(struct ibv_cq_ex * cq) +uint32_t ibv_wc_read_src_qp(struct ibv_cq_ex * cq) +int ibv_wc_read_wc_flags(struct ibv_cq_ex * cq) +uint32_t ibv_wc_read_slid(struct ibv_cq_ex * cq) +uint8_t ibv_wc_read_sl(struct ibv_cq_ex * cq) +uint8_t ibv_wc_read_dlid_path_bits(struct ibv_cq_ex * cq) +uint64_t ibv_wc_read_completion_ts(struct ibv_cq_ex * cq) +uint16_t ibv_wc_read_cvlan(struct ibv_cq_ex * cq) +uint32_t ibv_wc_read_flow_tag(struct ibv_cq_ex * cq) +int ibv_post_wq_recv(struct ibv_wq * wq,struct ibv_recv_wr * recv_wr,struct ibv_recv_wr ** bad_recv_wr) +struct verbs_context * verbs_get_ctx(struct ibv_context * ctx) +struct ibv_device ** ibv_get_device_list(int * num_devices) +void ibv_free_device_list(struct ibv_device ** list) +const char * ibv_get_device_name(struct ibv_device * device) +__be64 ibv_get_device_guid(struct ibv_device * device) +struct ibv_context * ibv_open_device(struct ibv_device * device) +int ibv_close_device(struct ibv_context * context) +int ibv_get_async_event(struct ibv_context * context,struct ibv_async_event * event) +void ibv_ack_async_event(struct ibv_async_event * event) +int ibv_query_device(struct ibv_context * context,struct ibv_device_attr * device_attr) +int ibv_query_port(struct ibv_context * context,uint8_t port_num,struct ibv_port_attr * port_attr) +int ___ibv_query_port(struct ibv_context * context,uint8_t port_num,struct ibv_port_attr * port_attr) +int ibv_query_gid(struct ibv_context * context,uint8_t port_num,int index,union ibv_gid * gid) +int ibv_query_pkey(struct ibv_context * context,uint8_t port_num,int index,__be16 * pkey) +struct ibv_pd * ibv_alloc_pd(struct ibv_context * context) +int ibv_dealloc_pd(struct ibv_pd * pd) +struct ibv_flow * ibv_create_flow(struct ibv_qp * qp,struct ibv_flow_attr * flow) +int ibv_destroy_flow(struct ibv_flow * flow_id) +struct ibv_xrcd * ibv_open_xrcd(struct ibv_context * context,struct ibv_xrcd_init_attr * xrcd_init_attr) +int ibv_close_xrcd(struct ibv_xrcd * xrcd) +struct ibv_mr * ibv_reg_mr(struct ibv_pd * pd,void * addr,int length,int access) +int ibv_rereg_mr(struct ibv_mr * mr,int flags,struct ibv_pd * pd,void * addr,int length,int access) +int ibv_dereg_mr(struct ibv_mr * mr) +struct ibv_mw * ibv_alloc_mw(struct ibv_pd * pd,enum ibv_mw_type type) +int ibv_dealloc_mw(struct ibv_mw * mw) +uint32_t ibv_inc_rkey(uint32_t rkey) +int ibv_bind_mw(struct ibv_qp * qp,struct ibv_mw * mw,struct ibv_mw_bind * mw_bind) +struct ibv_comp_channel * ibv_create_comp_channel(struct ibv_context * context) +int ibv_destroy_comp_channel(struct ibv_comp_channel * channel) +struct ibv_cq * ibv_create_cq(struct ibv_context * context,int cqe,void * cq_context,struct ibv_comp_channel * channel,int comp_vector) +struct ibv_cq_ex * ibv_create_cq_ex(struct ibv_context * context,struct ibv_cq_init_attr_ex * cq_attr) +int ibv_resize_cq(struct ibv_cq * cq,int cqe) +int ibv_destroy_cq(struct ibv_cq * cq) +int ibv_get_cq_event(struct ibv_comp_channel * channel,struct ibv_cq ** cq,void ** cq_context) +void ibv_ack_cq_events(struct ibv_cq * cq,unsigned int nevents) +int ibv_poll_cq(struct ibv_cq * cq,int num_entries,struct ibv_wc * wc) +int ibv_req_notify_cq(struct ibv_cq * cq,int solicited_only) +struct ibv_srq * ibv_create_srq(struct ibv_pd * pd,struct ibv_srq_init_attr * srq_init_attr) +struct ibv_srq * ibv_create_srq_ex(struct ibv_context * context,struct ibv_srq_init_attr_ex * srq_init_attr_ex) +int ibv_modify_srq(struct ibv_srq * srq,struct ibv_srq_attr * srq_attr,int srq_attr_mask) +int ibv_query_srq(struct ibv_srq * srq,struct ibv_srq_attr * srq_attr) +int ibv_get_srq_num(struct ibv_srq * srq,uint32_t * srq_num) +int ibv_destroy_srq(struct ibv_srq * srq) +int ibv_post_srq_recv(struct ibv_srq * srq,struct ibv_recv_wr * recv_wr,struct ibv_recv_wr ** bad_recv_wr) +struct ibv_qp * ibv_create_qp(struct ibv_pd * pd,struct ibv_qp_init_attr * qp_init_attr) +struct ibv_qp * ibv_create_qp_ex(struct ibv_context * context,struct ibv_qp_init_attr_ex * qp_init_attr_ex) +int ibv_query_rt_values_ex(struct ibv_context * context,struct ibv_values_ex * values) +int ibv_query_device_ex(struct ibv_context * context,const struct ibv_query_device_ex_input * input,struct ibv_device_attr_ex * attr) +struct ibv_qp * ibv_open_qp(struct ibv_context * context,struct ibv_qp_open_attr * qp_open_attr) +int ibv_modify_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,int attr_mask) +int ibv_query_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,int attr_mask,struct ibv_qp_init_attr * init_attr) +int ibv_destroy_qp(struct ibv_qp * qp) +struct ibv_wq * ibv_create_wq(struct ibv_context * context,struct ibv_wq_init_attr * wq_init_attr) +int ibv_modify_wq(struct ibv_wq * wq,struct ibv_wq_attr * wq_attr) +int ibv_destroy_wq(struct ibv_wq * wq) +struct ibv_rwq_ind_table * ibv_create_rwq_ind_table(struct ibv_context * context,struct ibv_rwq_ind_table_init_attr * init_attr) +int ibv_destroy_rwq_ind_table(struct ibv_rwq_ind_table * rwq_ind_table) +int ibv_post_send(struct ibv_qp * qp,struct ibv_send_wr * wr,struct ibv_send_wr ** bad_wr) +int ibv_post_recv(struct ibv_qp * qp,struct ibv_recv_wr * wr,struct ibv_recv_wr ** bad_wr) +struct ibv_ah * ibv_create_ah(struct ibv_pd * pd,struct ibv_ah_attr * attr) +int ibv_init_ah_from_wc(struct ibv_context * context,uint8_t port_num,struct ibv_wc * wc,struct ibv_grh * grh,struct ibv_ah_attr * ah_attr) +struct ibv_ah * ibv_create_ah_from_wc(struct ibv_pd * pd,struct ibv_wc * wc,struct ibv_grh * grh,uint8_t port_num) +int ibv_destroy_ah(struct ibv_ah * ah) +int ibv_attach_mcast(struct ibv_qp * qp,const union ibv_gid * gid,uint16_t lid) +int ibv_detach_mcast(struct ibv_qp * qp,const union ibv_gid * gid,uint16_t lid) +int ibv_fork_init() +const char * ibv_node_type_str(enum ibv_node_type node_type) +const char * ibv_port_state_str(enum ibv_port_state port_state) +const char * ibv_event_type_str(enum ibv_event_type event) +int ibv_resolve_eth_l2_from_gid(struct ibv_context * context,struct ibv_ah_attr * attr,uint8_t [6] eth_mac,uint16_t * vid) +int ibv_is_qpt_supported(uint32_t caps,enum ibv_qp_type qpt) diff --git a/tools/ibv_code_generator/ibv_gen.c b/tools/ibv_code_generator/ibv_gen.c new file mode 100644 index 000000000..3f54b3fa6 --- /dev/null +++ b/tools/ibv_code_generator/ibv_gen.c @@ -0,0 +1,1805 @@ +typedef struct { + // Parameters: + enum ibv_wc_status status; + // Return value: + const char * ret; +} __attribute__((packed)) uhyve_ibv_wc_status_str_t; + +const char * ibv_wc_status_str(enum ibv_wc_status status) { + uhyve_ibv_wc_status_str_t uhyve_args; + uhyve_args->status = status; + uhyve_args->ret = kmalloc(sizeof(const char)); + uhyve_send(UHYVE_PORT_IBV_WC_STATUS_STR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + enum ibv_rate rate; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_rate_to_mult_t; + +int ibv_rate_to_mult(enum ibv_rate rate) { + uhyve_ibv_rate_to_mult_t uhyve_args; + uhyve_args->rate = rate; + uhyve_send(UHYVE_PORT_IBV_RATE_TO_MULT, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + int mult; + // Return value: + enum ibv_rate ret; +} __attribute__((packed)) uhyve_mult_to_ibv_rate_t; + +enum ibv_rate mult_to_ibv_rate(int mult) { + uhyve_mult_to_ibv_rate_t uhyve_args; + uhyve_args->mult = mult; + uhyve_send(UHYVE_PORT_MULT_TO_IBV_RATE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + enum ibv_rate rate; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_rate_to_mbps_t; + +int ibv_rate_to_mbps(enum ibv_rate rate) { + uhyve_ibv_rate_to_mbps_t uhyve_args; + uhyve_args->rate = rate; + uhyve_send(UHYVE_PORT_IBV_RATE_TO_MBPS, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + int mbps; + // Return value: + enum ibv_rate ret; +} __attribute__((packed)) uhyve_mbps_to_ibv_rate_t; + +enum ibv_rate mbps_to_ibv_rate(int mbps) { + uhyve_mbps_to_ibv_rate_t uhyve_args; + uhyve_args->mbps = mbps; + uhyve_send(UHYVE_PORT_MBPS_TO_IBV_RATE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + struct ibv_cq * ret; +} __attribute__((packed)) uhyve_ibv_cq_ex_to_cq_t; + +struct ibv_cq * ibv_cq_ex_to_cq(struct ibv_cq_ex * cq) { + uhyve_ibv_cq_ex_to_cq_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_args->ret = kmalloc(sizeof(struct ibv_cq)); + uhyve_send(UHYVE_PORT_IBV_CQ_EX_TO_CQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + struct ibv_poll_cq_attr * attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_start_poll_t; + +int ibv_start_poll(struct ibv_cq_ex * cq, struct ibv_poll_cq_attr * attr) { + uhyve_ibv_start_poll_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_args->attr = (struct ibv_poll_cq_attr *) virt_to_phys((size_t) attr); + uhyve_send(UHYVE_PORT_IBV_START_POLL, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_next_poll_t; + +int ibv_next_poll(struct ibv_cq_ex * cq) { + uhyve_ibv_next_poll_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_NEXT_POLL, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + void ret; +} __attribute__((packed)) uhyve_ibv_end_poll_t; + +void ibv_end_poll(struct ibv_cq_ex * cq) { + uhyve_ibv_end_poll_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_END_POLL, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + enum ibv_wc_opcode ret; +} __attribute__((packed)) uhyve_ibv_wc_read_opcode_t; + +enum ibv_wc_opcode ibv_wc_read_opcode(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_opcode_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_OPCODE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_vendor_err_t; + +uint32_t ibv_wc_read_vendor_err(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_vendor_err_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_VENDOR_ERR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_byte_len_t; + +uint32_t ibv_wc_read_byte_len(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_byte_len_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_BYTE_LEN, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + __be32 ret; +} __attribute__((packed)) uhyve_ibv_wc_read_imm_data_t; + +__be32 ibv_wc_read_imm_data(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_imm_data_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_IMM_DATA, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_invalidated_rkey_t; + +uint32_t ibv_wc_read_invalidated_rkey(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_invalidated_rkey_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_INVALIDATED_RKEY, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_qp_num_t; + +uint32_t ibv_wc_read_qp_num(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_qp_num_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_QP_NUM, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_src_qp_t; + +uint32_t ibv_wc_read_src_qp(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_src_qp_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_SRC_QP, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_wc_read_wc_flags_t; + +int ibv_wc_read_wc_flags(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_wc_flags_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_WC_FLAGS, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_slid_t; + +uint32_t ibv_wc_read_slid(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_slid_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_SLID, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint8_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_sl_t; + +uint8_t ibv_wc_read_sl(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_sl_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_SL, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint8_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_dlid_path_bits_t; + +uint8_t ibv_wc_read_dlid_path_bits(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_dlid_path_bits_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_DLID_PATH_BITS, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint64_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_completion_ts_t; + +uint64_t ibv_wc_read_completion_ts(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_completion_ts_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_COMPLETION_TS, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint16_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_cvlan_t; + +uint16_t ibv_wc_read_cvlan(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_cvlan_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_CVLAN, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq_ex * cq; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_wc_read_flow_tag_t; + +uint32_t ibv_wc_read_flow_tag(struct ibv_cq_ex * cq) { + uhyve_ibv_wc_read_flow_tag_t uhyve_args; + uhyve_args->cq = (struct ibv_cq_ex *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_WC_READ_FLOW_TAG, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_wq * wq; + struct ibv_recv_wr * recv_wr; + struct ibv_recv_wr ** bad_recv_wr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_post_wq_recv_t; + +int ibv_post_wq_recv(struct ibv_wq * wq, struct ibv_recv_wr * recv_wr, struct ibv_recv_wr ** bad_recv_wr) { + uhyve_ibv_post_wq_recv_t uhyve_args; + uhyve_args->wq = (struct ibv_wq *) virt_to_phys((size_t) wq); + uhyve_args->recv_wr = (struct ibv_recv_wr *) virt_to_phys((size_t) recv_wr); + // TODO: Take care of ** parameter. + uhyve_send(UHYVE_PORT_IBV_POST_WQ_RECV, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * ctx; + // Return value: + struct verbs_context * ret; +} __attribute__((packed)) uhyve_verbs_get_ctx_t; + +struct verbs_context * verbs_get_ctx(struct ibv_context * ctx) { + uhyve_verbs_get_ctx_t uhyve_args; + uhyve_args->ctx = (struct ibv_context *) virt_to_phys((size_t) ctx); + uhyve_args->ret = kmalloc(sizeof(struct verbs_context)); + uhyve_send(UHYVE_PORT_VERBS_GET_CTX, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + int * num_devices; + // Return value: + struct ibv_device ** ret; +} __attribute__((packed)) uhyve_ibv_get_device_list_t; + +struct ibv_device ** ibv_get_device_list(int * num_devices) { + uhyve_ibv_get_device_list_t uhyve_args; + uhyve_args->num_devices = (int *) virt_to_phys((size_t) num_devices); + // TODO: Take care of return value. + uhyve_send(UHYVE_PORT_IBV_GET_DEVICE_LIST, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_device ** list; + // Return value: + void ret; +} __attribute__((packed)) uhyve_ibv_free_device_list_t; + +void ibv_free_device_list(struct ibv_device ** list) { + uhyve_ibv_free_device_list_t uhyve_args; + // TODO: Take care of ** parameter. + uhyve_send(UHYVE_PORT_IBV_FREE_DEVICE_LIST, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_device * device; + // Return value: + const char * ret; +} __attribute__((packed)) uhyve_ibv_get_device_name_t; + +const char * ibv_get_device_name(struct ibv_device * device) { + uhyve_ibv_get_device_name_t uhyve_args; + uhyve_args->device = (struct ibv_device *) virt_to_phys((size_t) device); + uhyve_args->ret = kmalloc(sizeof(const char)); + uhyve_send(UHYVE_PORT_IBV_GET_DEVICE_NAME, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_device * device; + // Return value: + __be64 ret; +} __attribute__((packed)) uhyve_ibv_get_device_guid_t; + +__be64 ibv_get_device_guid(struct ibv_device * device) { + uhyve_ibv_get_device_guid_t uhyve_args; + uhyve_args->device = (struct ibv_device *) virt_to_phys((size_t) device); + uhyve_send(UHYVE_PORT_IBV_GET_DEVICE_GUID, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_device * device; + // Return value: + struct ibv_context * ret; +} __attribute__((packed)) uhyve_ibv_open_device_t; + +struct ibv_context * ibv_open_device(struct ibv_device * device) { + uhyve_ibv_open_device_t uhyve_args; + uhyve_args->device = (struct ibv_device *) virt_to_phys((size_t) device); + uhyve_args->ret = kmalloc(sizeof(struct ibv_context)); + uhyve_send(UHYVE_PORT_IBV_OPEN_DEVICE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_close_device_t; + +int ibv_close_device(struct ibv_context * context) { + uhyve_ibv_close_device_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_send(UHYVE_PORT_IBV_CLOSE_DEVICE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_async_event * event; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_get_async_event_t; + +int ibv_get_async_event(struct ibv_context * context, struct ibv_async_event * event) { + uhyve_ibv_get_async_event_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->event = (struct ibv_async_event *) virt_to_phys((size_t) event); + uhyve_send(UHYVE_PORT_IBV_GET_ASYNC_EVENT, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_async_event * event; + // Return value: + void ret; +} __attribute__((packed)) uhyve_ibv_ack_async_event_t; + +void ibv_ack_async_event(struct ibv_async_event * event) { + uhyve_ibv_ack_async_event_t uhyve_args; + uhyve_args->event = (struct ibv_async_event *) virt_to_phys((size_t) event); + uhyve_send(UHYVE_PORT_IBV_ACK_ASYNC_EVENT, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_device_attr * device_attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_device_t; + +int ibv_query_device(struct ibv_context * context, struct ibv_device_attr * device_attr) { + uhyve_ibv_query_device_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->device_attr = (struct ibv_device_attr *) virt_to_phys((size_t) device_attr); + uhyve_send(UHYVE_PORT_IBV_QUERY_DEVICE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + uint8_t port_num; + struct ibv_port_attr * port_attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_port_t; + +int ibv_query_port(struct ibv_context * context, uint8_t port_num, struct ibv_port_attr * port_attr) { + uhyve_ibv_query_port_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->port_num = port_num; + uhyve_args->port_attr = (struct ibv_port_attr *) virt_to_phys((size_t) port_attr); + uhyve_send(UHYVE_PORT_IBV_QUERY_PORT, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + uint8_t port_num; + struct ibv_port_attr * port_attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve____ibv_query_port_t; + +int ___ibv_query_port(struct ibv_context * context, uint8_t port_num, struct ibv_port_attr * port_attr) { + uhyve____ibv_query_port_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->port_num = port_num; + uhyve_args->port_attr = (struct ibv_port_attr *) virt_to_phys((size_t) port_attr); + uhyve_send(UHYVE_PORT____IBV_QUERY_PORT, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + uint8_t port_num; + int index; + union ibv_gid * gid; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_gid_t; + +int ibv_query_gid(struct ibv_context * context, uint8_t port_num, int index, union ibv_gid * gid) { + uhyve_ibv_query_gid_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->port_num = port_num; + uhyve_args->index = index; + uhyve_args->gid = (union ibv_gid *) virt_to_phys((size_t) gid); + uhyve_send(UHYVE_PORT_IBV_QUERY_GID, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + uint8_t port_num; + int index; + __be16 * pkey; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_pkey_t; + +int ibv_query_pkey(struct ibv_context * context, uint8_t port_num, int index, __be16 * pkey) { + uhyve_ibv_query_pkey_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->port_num = port_num; + uhyve_args->index = index; + uhyve_args->pkey = (__be16 *) virt_to_phys((size_t) pkey); + uhyve_send(UHYVE_PORT_IBV_QUERY_PKEY, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + // Return value: + struct ibv_pd * ret; +} __attribute__((packed)) uhyve_ibv_alloc_pd_t; + +struct ibv_pd * ibv_alloc_pd(struct ibv_context * context) { + uhyve_ibv_alloc_pd_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->ret = kmalloc(sizeof(struct ibv_pd)); + uhyve_send(UHYVE_PORT_IBV_ALLOC_PD, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_pd * pd; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_dealloc_pd_t; + +int ibv_dealloc_pd(struct ibv_pd * pd) { + uhyve_ibv_dealloc_pd_t uhyve_args; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_send(UHYVE_PORT_IBV_DEALLOC_PD, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + struct ibv_flow_attr * flow; + // Return value: + struct ibv_flow * ret; +} __attribute__((packed)) uhyve_ibv_create_flow_t; + +struct ibv_flow * ibv_create_flow(struct ibv_qp * qp, struct ibv_flow_attr * flow) { + uhyve_ibv_create_flow_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->flow = (struct ibv_flow_attr *) virt_to_phys((size_t) flow); + uhyve_args->ret = kmalloc(sizeof(struct ibv_flow)); + uhyve_send(UHYVE_PORT_IBV_CREATE_FLOW, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_flow * flow_id; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_flow_t; + +int ibv_destroy_flow(struct ibv_flow * flow_id) { + uhyve_ibv_destroy_flow_t uhyve_args; + uhyve_args->flow_id = (struct ibv_flow *) virt_to_phys((size_t) flow_id); + uhyve_send(UHYVE_PORT_IBV_DESTROY_FLOW, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_xrcd_init_attr * xrcd_init_attr; + // Return value: + struct ibv_xrcd * ret; +} __attribute__((packed)) uhyve_ibv_open_xrcd_t; + +struct ibv_xrcd * ibv_open_xrcd(struct ibv_context * context, struct ibv_xrcd_init_attr * xrcd_init_attr) { + uhyve_ibv_open_xrcd_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->xrcd_init_attr = (struct ibv_xrcd_init_attr *) virt_to_phys((size_t) xrcd_init_attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_xrcd)); + uhyve_send(UHYVE_PORT_IBV_OPEN_XRCD, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_xrcd * xrcd; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_close_xrcd_t; + +int ibv_close_xrcd(struct ibv_xrcd * xrcd) { + uhyve_ibv_close_xrcd_t uhyve_args; + uhyve_args->xrcd = (struct ibv_xrcd *) virt_to_phys((size_t) xrcd); + uhyve_send(UHYVE_PORT_IBV_CLOSE_XRCD, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_pd * pd; + void * addr; + int length; + int access; + // Return value: + struct ibv_mr * ret; +} __attribute__((packed)) uhyve_ibv_reg_mr_t; + +struct ibv_mr * ibv_reg_mr(struct ibv_pd * pd, void * addr, int length, int access) { + uhyve_ibv_reg_mr_t uhyve_args; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_args->addr = (void *) virt_to_phys((size_t) addr); + uhyve_args->length = length; + uhyve_args->access = access; + uhyve_args->ret = kmalloc(sizeof(struct ibv_mr)); + uhyve_send(UHYVE_PORT_IBV_REG_MR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_mr * mr; + int flags; + struct ibv_pd * pd; + void * addr; + int length; + int access; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_rereg_mr_t; + +int ibv_rereg_mr(struct ibv_mr * mr, int flags, struct ibv_pd * pd, void * addr, int length, int access) { + uhyve_ibv_rereg_mr_t uhyve_args; + uhyve_args->mr = (struct ibv_mr *) virt_to_phys((size_t) mr); + uhyve_args->flags = flags; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_args->addr = (void *) virt_to_phys((size_t) addr); + uhyve_args->length = length; + uhyve_args->access = access; + uhyve_send(UHYVE_PORT_IBV_REREG_MR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_mr * mr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_dereg_mr_t; + +int ibv_dereg_mr(struct ibv_mr * mr) { + uhyve_ibv_dereg_mr_t uhyve_args; + uhyve_args->mr = (struct ibv_mr *) virt_to_phys((size_t) mr); + uhyve_send(UHYVE_PORT_IBV_DEREG_MR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_pd * pd; + enum ibv_mw_type type; + // Return value: + struct ibv_mw * ret; +} __attribute__((packed)) uhyve_ibv_alloc_mw_t; + +struct ibv_mw * ibv_alloc_mw(struct ibv_pd * pd, enum ibv_mw_type type) { + uhyve_ibv_alloc_mw_t uhyve_args; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_args->type = type; + uhyve_args->ret = kmalloc(sizeof(struct ibv_mw)); + uhyve_send(UHYVE_PORT_IBV_ALLOC_MW, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_mw * mw; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_dealloc_mw_t; + +int ibv_dealloc_mw(struct ibv_mw * mw) { + uhyve_ibv_dealloc_mw_t uhyve_args; + uhyve_args->mw = (struct ibv_mw *) virt_to_phys((size_t) mw); + uhyve_send(UHYVE_PORT_IBV_DEALLOC_MW, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + uint32_t rkey; + // Return value: + uint32_t ret; +} __attribute__((packed)) uhyve_ibv_inc_rkey_t; + +uint32_t ibv_inc_rkey(uint32_t rkey) { + uhyve_ibv_inc_rkey_t uhyve_args; + uhyve_args->rkey = rkey; + uhyve_send(UHYVE_PORT_IBV_INC_RKEY, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + struct ibv_mw * mw; + struct ibv_mw_bind * mw_bind; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_bind_mw_t; + +int ibv_bind_mw(struct ibv_qp * qp, struct ibv_mw * mw, struct ibv_mw_bind * mw_bind) { + uhyve_ibv_bind_mw_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->mw = (struct ibv_mw *) virt_to_phys((size_t) mw); + uhyve_args->mw_bind = (struct ibv_mw_bind *) virt_to_phys((size_t) mw_bind); + uhyve_send(UHYVE_PORT_IBV_BIND_MW, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + // Return value: + struct ibv_comp_channel * ret; +} __attribute__((packed)) uhyve_ibv_create_comp_channel_t; + +struct ibv_comp_channel * ibv_create_comp_channel(struct ibv_context * context) { + uhyve_ibv_create_comp_channel_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->ret = kmalloc(sizeof(struct ibv_comp_channel)); + uhyve_send(UHYVE_PORT_IBV_CREATE_COMP_CHANNEL, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_comp_channel * channel; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_comp_channel_t; + +int ibv_destroy_comp_channel(struct ibv_comp_channel * channel) { + uhyve_ibv_destroy_comp_channel_t uhyve_args; + uhyve_args->channel = (struct ibv_comp_channel *) virt_to_phys((size_t) channel); + uhyve_send(UHYVE_PORT_IBV_DESTROY_COMP_CHANNEL, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + int cqe; + void * cq_context; + struct ibv_comp_channel * channel; + int comp_vector; + // Return value: + struct ibv_cq * ret; +} __attribute__((packed)) uhyve_ibv_create_cq_t; + +struct ibv_cq * ibv_create_cq(struct ibv_context * context, int cqe, void * cq_context, struct ibv_comp_channel * channel, int comp_vector) { + uhyve_ibv_create_cq_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->cqe = cqe; + uhyve_args->cq_context = (void *) virt_to_phys((size_t) cq_context); + uhyve_args->channel = (struct ibv_comp_channel *) virt_to_phys((size_t) channel); + uhyve_args->comp_vector = comp_vector; + uhyve_args->ret = kmalloc(sizeof(struct ibv_cq)); + uhyve_send(UHYVE_PORT_IBV_CREATE_CQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_cq_init_attr_ex * cq_attr; + // Return value: + struct ibv_cq_ex * ret; +} __attribute__((packed)) uhyve_ibv_create_cq_ex_t; + +struct ibv_cq_ex * ibv_create_cq_ex(struct ibv_context * context, struct ibv_cq_init_attr_ex * cq_attr) { + uhyve_ibv_create_cq_ex_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->cq_attr = (struct ibv_cq_init_attr_ex *) virt_to_phys((size_t) cq_attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_cq_ex)); + uhyve_send(UHYVE_PORT_IBV_CREATE_CQ_EX, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq * cq; + int cqe; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_resize_cq_t; + +int ibv_resize_cq(struct ibv_cq * cq, int cqe) { + uhyve_ibv_resize_cq_t uhyve_args; + uhyve_args->cq = (struct ibv_cq *) virt_to_phys((size_t) cq); + uhyve_args->cqe = cqe; + uhyve_send(UHYVE_PORT_IBV_RESIZE_CQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq * cq; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_cq_t; + +int ibv_destroy_cq(struct ibv_cq * cq) { + uhyve_ibv_destroy_cq_t uhyve_args; + uhyve_args->cq = (struct ibv_cq *) virt_to_phys((size_t) cq); + uhyve_send(UHYVE_PORT_IBV_DESTROY_CQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_comp_channel * channel; + struct ibv_cq ** cq; + void ** cq_context; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_get_cq_event_t; + +int ibv_get_cq_event(struct ibv_comp_channel * channel, struct ibv_cq ** cq, void ** cq_context) { + uhyve_ibv_get_cq_event_t uhyve_args; + uhyve_args->channel = (struct ibv_comp_channel *) virt_to_phys((size_t) channel); + // TODO: Take care of ** parameter. + // TODO: Take care of ** parameter. + uhyve_send(UHYVE_PORT_IBV_GET_CQ_EVENT, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq * cq; + unsigned int nevents; + // Return value: + void ret; +} __attribute__((packed)) uhyve_ibv_ack_cq_events_t; + +void ibv_ack_cq_events(struct ibv_cq * cq, unsigned int nevents) { + uhyve_ibv_ack_cq_events_t uhyve_args; + uhyve_args->cq = (struct ibv_cq *) virt_to_phys((size_t) cq); + uhyve_args->nevents = nevents; + uhyve_send(UHYVE_PORT_IBV_ACK_CQ_EVENTS, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq * cq; + int num_entries; + struct ibv_wc * wc; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_poll_cq_t; + +int ibv_poll_cq(struct ibv_cq * cq, int num_entries, struct ibv_wc * wc) { + uhyve_ibv_poll_cq_t uhyve_args; + uhyve_args->cq = (struct ibv_cq *) virt_to_phys((size_t) cq); + uhyve_args->num_entries = num_entries; + uhyve_args->wc = (struct ibv_wc *) virt_to_phys((size_t) wc); + uhyve_send(UHYVE_PORT_IBV_POLL_CQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_cq * cq; + int solicited_only; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_req_notify_cq_t; + +int ibv_req_notify_cq(struct ibv_cq * cq, int solicited_only) { + uhyve_ibv_req_notify_cq_t uhyve_args; + uhyve_args->cq = (struct ibv_cq *) virt_to_phys((size_t) cq); + uhyve_args->solicited_only = solicited_only; + uhyve_send(UHYVE_PORT_IBV_REQ_NOTIFY_CQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_pd * pd; + struct ibv_srq_init_attr * srq_init_attr; + // Return value: + struct ibv_srq * ret; +} __attribute__((packed)) uhyve_ibv_create_srq_t; + +struct ibv_srq * ibv_create_srq(struct ibv_pd * pd, struct ibv_srq_init_attr * srq_init_attr) { + uhyve_ibv_create_srq_t uhyve_args; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_args->srq_init_attr = (struct ibv_srq_init_attr *) virt_to_phys((size_t) srq_init_attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_srq)); + uhyve_send(UHYVE_PORT_IBV_CREATE_SRQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_srq_init_attr_ex * srq_init_attr_ex; + // Return value: + struct ibv_srq * ret; +} __attribute__((packed)) uhyve_ibv_create_srq_ex_t; + +struct ibv_srq * ibv_create_srq_ex(struct ibv_context * context, struct ibv_srq_init_attr_ex * srq_init_attr_ex) { + uhyve_ibv_create_srq_ex_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->srq_init_attr_ex = (struct ibv_srq_init_attr_ex *) virt_to_phys((size_t) srq_init_attr_ex); + uhyve_args->ret = kmalloc(sizeof(struct ibv_srq)); + uhyve_send(UHYVE_PORT_IBV_CREATE_SRQ_EX, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_srq * srq; + struct ibv_srq_attr * srq_attr; + int srq_attr_mask; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_modify_srq_t; + +int ibv_modify_srq(struct ibv_srq * srq, struct ibv_srq_attr * srq_attr, int srq_attr_mask) { + uhyve_ibv_modify_srq_t uhyve_args; + uhyve_args->srq = (struct ibv_srq *) virt_to_phys((size_t) srq); + uhyve_args->srq_attr = (struct ibv_srq_attr *) virt_to_phys((size_t) srq_attr); + uhyve_args->srq_attr_mask = srq_attr_mask; + uhyve_send(UHYVE_PORT_IBV_MODIFY_SRQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_srq * srq; + struct ibv_srq_attr * srq_attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_srq_t; + +int ibv_query_srq(struct ibv_srq * srq, struct ibv_srq_attr * srq_attr) { + uhyve_ibv_query_srq_t uhyve_args; + uhyve_args->srq = (struct ibv_srq *) virt_to_phys((size_t) srq); + uhyve_args->srq_attr = (struct ibv_srq_attr *) virt_to_phys((size_t) srq_attr); + uhyve_send(UHYVE_PORT_IBV_QUERY_SRQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_srq * srq; + uint32_t * srq_num; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_get_srq_num_t; + +int ibv_get_srq_num(struct ibv_srq * srq, uint32_t * srq_num) { + uhyve_ibv_get_srq_num_t uhyve_args; + uhyve_args->srq = (struct ibv_srq *) virt_to_phys((size_t) srq); + uhyve_args->srq_num = (uint32_t *) virt_to_phys((size_t) srq_num); + uhyve_send(UHYVE_PORT_IBV_GET_SRQ_NUM, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_srq * srq; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_srq_t; + +int ibv_destroy_srq(struct ibv_srq * srq) { + uhyve_ibv_destroy_srq_t uhyve_args; + uhyve_args->srq = (struct ibv_srq *) virt_to_phys((size_t) srq); + uhyve_send(UHYVE_PORT_IBV_DESTROY_SRQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_srq * srq; + struct ibv_recv_wr * recv_wr; + struct ibv_recv_wr ** bad_recv_wr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_post_srq_recv_t; + +int ibv_post_srq_recv(struct ibv_srq * srq, struct ibv_recv_wr * recv_wr, struct ibv_recv_wr ** bad_recv_wr) { + uhyve_ibv_post_srq_recv_t uhyve_args; + uhyve_args->srq = (struct ibv_srq *) virt_to_phys((size_t) srq); + uhyve_args->recv_wr = (struct ibv_recv_wr *) virt_to_phys((size_t) recv_wr); + // TODO: Take care of ** parameter. + uhyve_send(UHYVE_PORT_IBV_POST_SRQ_RECV, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_pd * pd; + struct ibv_qp_init_attr * qp_init_attr; + // Return value: + struct ibv_qp * ret; +} __attribute__((packed)) uhyve_ibv_create_qp_t; + +struct ibv_qp * ibv_create_qp(struct ibv_pd * pd, struct ibv_qp_init_attr * qp_init_attr) { + uhyve_ibv_create_qp_t uhyve_args; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_args->qp_init_attr = (struct ibv_qp_init_attr *) virt_to_phys((size_t) qp_init_attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_qp)); + uhyve_send(UHYVE_PORT_IBV_CREATE_QP, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_qp_init_attr_ex * qp_init_attr_ex; + // Return value: + struct ibv_qp * ret; +} __attribute__((packed)) uhyve_ibv_create_qp_ex_t; + +struct ibv_qp * ibv_create_qp_ex(struct ibv_context * context, struct ibv_qp_init_attr_ex * qp_init_attr_ex) { + uhyve_ibv_create_qp_ex_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->qp_init_attr_ex = (struct ibv_qp_init_attr_ex *) virt_to_phys((size_t) qp_init_attr_ex); + uhyve_args->ret = kmalloc(sizeof(struct ibv_qp)); + uhyve_send(UHYVE_PORT_IBV_CREATE_QP_EX, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_values_ex * values; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_rt_values_ex_t; + +int ibv_query_rt_values_ex(struct ibv_context * context, struct ibv_values_ex * values) { + uhyve_ibv_query_rt_values_ex_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->values = (struct ibv_values_ex *) virt_to_phys((size_t) values); + uhyve_send(UHYVE_PORT_IBV_QUERY_RT_VALUES_EX, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + const struct ibv_query_device_ex_input * input; + struct ibv_device_attr_ex * attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_device_ex_t; + +int ibv_query_device_ex(struct ibv_context * context, const struct ibv_query_device_ex_input * input, struct ibv_device_attr_ex * attr) { + uhyve_ibv_query_device_ex_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->input = (const struct ibv_query_device_ex_input *) virt_to_phys((size_t) input); + uhyve_args->attr = (struct ibv_device_attr_ex *) virt_to_phys((size_t) attr); + uhyve_send(UHYVE_PORT_IBV_QUERY_DEVICE_EX, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_qp_open_attr * qp_open_attr; + // Return value: + struct ibv_qp * ret; +} __attribute__((packed)) uhyve_ibv_open_qp_t; + +struct ibv_qp * ibv_open_qp(struct ibv_context * context, struct ibv_qp_open_attr * qp_open_attr) { + uhyve_ibv_open_qp_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->qp_open_attr = (struct ibv_qp_open_attr *) virt_to_phys((size_t) qp_open_attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_qp)); + uhyve_send(UHYVE_PORT_IBV_OPEN_QP, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + struct ibv_qp_attr * attr; + int attr_mask; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_modify_qp_t; + +int ibv_modify_qp(struct ibv_qp * qp, struct ibv_qp_attr * attr, int attr_mask) { + uhyve_ibv_modify_qp_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->attr = (struct ibv_qp_attr *) virt_to_phys((size_t) attr); + uhyve_args->attr_mask = attr_mask; + uhyve_send(UHYVE_PORT_IBV_MODIFY_QP, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + struct ibv_qp_attr * attr; + int attr_mask; + struct ibv_qp_init_attr * init_attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_query_qp_t; + +int ibv_query_qp(struct ibv_qp * qp, struct ibv_qp_attr * attr, int attr_mask, struct ibv_qp_init_attr * init_attr) { + uhyve_ibv_query_qp_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->attr = (struct ibv_qp_attr *) virt_to_phys((size_t) attr); + uhyve_args->attr_mask = attr_mask; + uhyve_args->init_attr = (struct ibv_qp_init_attr *) virt_to_phys((size_t) init_attr); + uhyve_send(UHYVE_PORT_IBV_QUERY_QP, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_qp_t; + +int ibv_destroy_qp(struct ibv_qp * qp) { + uhyve_ibv_destroy_qp_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_send(UHYVE_PORT_IBV_DESTROY_QP, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_wq_init_attr * wq_init_attr; + // Return value: + struct ibv_wq * ret; +} __attribute__((packed)) uhyve_ibv_create_wq_t; + +struct ibv_wq * ibv_create_wq(struct ibv_context * context, struct ibv_wq_init_attr * wq_init_attr) { + uhyve_ibv_create_wq_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->wq_init_attr = (struct ibv_wq_init_attr *) virt_to_phys((size_t) wq_init_attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_wq)); + uhyve_send(UHYVE_PORT_IBV_CREATE_WQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_wq * wq; + struct ibv_wq_attr * wq_attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_modify_wq_t; + +int ibv_modify_wq(struct ibv_wq * wq, struct ibv_wq_attr * wq_attr) { + uhyve_ibv_modify_wq_t uhyve_args; + uhyve_args->wq = (struct ibv_wq *) virt_to_phys((size_t) wq); + uhyve_args->wq_attr = (struct ibv_wq_attr *) virt_to_phys((size_t) wq_attr); + uhyve_send(UHYVE_PORT_IBV_MODIFY_WQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_wq * wq; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_wq_t; + +int ibv_destroy_wq(struct ibv_wq * wq) { + uhyve_ibv_destroy_wq_t uhyve_args; + uhyve_args->wq = (struct ibv_wq *) virt_to_phys((size_t) wq); + uhyve_send(UHYVE_PORT_IBV_DESTROY_WQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_rwq_ind_table_init_attr * init_attr; + // Return value: + struct ibv_rwq_ind_table * ret; +} __attribute__((packed)) uhyve_ibv_create_rwq_ind_table_t; + +struct ibv_rwq_ind_table * ibv_create_rwq_ind_table(struct ibv_context * context, struct ibv_rwq_ind_table_init_attr * init_attr) { + uhyve_ibv_create_rwq_ind_table_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->init_attr = (struct ibv_rwq_ind_table_init_attr *) virt_to_phys((size_t) init_attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_rwq_ind_table)); + uhyve_send(UHYVE_PORT_IBV_CREATE_RWQ_IND_TABLE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_rwq_ind_table * rwq_ind_table; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_rwq_ind_table_t; + +int ibv_destroy_rwq_ind_table(struct ibv_rwq_ind_table * rwq_ind_table) { + uhyve_ibv_destroy_rwq_ind_table_t uhyve_args; + uhyve_args->rwq_ind_table = (struct ibv_rwq_ind_table *) virt_to_phys((size_t) rwq_ind_table); + uhyve_send(UHYVE_PORT_IBV_DESTROY_RWQ_IND_TABLE, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + struct ibv_send_wr * wr; + struct ibv_send_wr ** bad_wr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_post_send_t; + +int ibv_post_send(struct ibv_qp * qp, struct ibv_send_wr * wr, struct ibv_send_wr ** bad_wr) { + uhyve_ibv_post_send_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->wr = (struct ibv_send_wr *) virt_to_phys((size_t) wr); + // TODO: Take care of ** parameter. + uhyve_send(UHYVE_PORT_IBV_POST_SEND, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + struct ibv_recv_wr * wr; + struct ibv_recv_wr ** bad_wr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_post_recv_t; + +int ibv_post_recv(struct ibv_qp * qp, struct ibv_recv_wr * wr, struct ibv_recv_wr ** bad_wr) { + uhyve_ibv_post_recv_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->wr = (struct ibv_recv_wr *) virt_to_phys((size_t) wr); + // TODO: Take care of ** parameter. + uhyve_send(UHYVE_PORT_IBV_POST_RECV, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_pd * pd; + struct ibv_ah_attr * attr; + // Return value: + struct ibv_ah * ret; +} __attribute__((packed)) uhyve_ibv_create_ah_t; + +struct ibv_ah * ibv_create_ah(struct ibv_pd * pd, struct ibv_ah_attr * attr) { + uhyve_ibv_create_ah_t uhyve_args; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_args->attr = (struct ibv_ah_attr *) virt_to_phys((size_t) attr); + uhyve_args->ret = kmalloc(sizeof(struct ibv_ah)); + uhyve_send(UHYVE_PORT_IBV_CREATE_AH, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + uint8_t port_num; + struct ibv_wc * wc; + struct ibv_grh * grh; + struct ibv_ah_attr * ah_attr; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_init_ah_from_wc_t; + +int ibv_init_ah_from_wc(struct ibv_context * context, uint8_t port_num, struct ibv_wc * wc, struct ibv_grh * grh, struct ibv_ah_attr * ah_attr) { + uhyve_ibv_init_ah_from_wc_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->port_num = port_num; + uhyve_args->wc = (struct ibv_wc *) virt_to_phys((size_t) wc); + uhyve_args->grh = (struct ibv_grh *) virt_to_phys((size_t) grh); + uhyve_args->ah_attr = (struct ibv_ah_attr *) virt_to_phys((size_t) ah_attr); + uhyve_send(UHYVE_PORT_IBV_INIT_AH_FROM_WC, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_pd * pd; + struct ibv_wc * wc; + struct ibv_grh * grh; + uint8_t port_num; + // Return value: + struct ibv_ah * ret; +} __attribute__((packed)) uhyve_ibv_create_ah_from_wc_t; + +struct ibv_ah * ibv_create_ah_from_wc(struct ibv_pd * pd, struct ibv_wc * wc, struct ibv_grh * grh, uint8_t port_num) { + uhyve_ibv_create_ah_from_wc_t uhyve_args; + uhyve_args->pd = (struct ibv_pd *) virt_to_phys((size_t) pd); + uhyve_args->wc = (struct ibv_wc *) virt_to_phys((size_t) wc); + uhyve_args->grh = (struct ibv_grh *) virt_to_phys((size_t) grh); + uhyve_args->port_num = port_num; + uhyve_args->ret = kmalloc(sizeof(struct ibv_ah)); + uhyve_send(UHYVE_PORT_IBV_CREATE_AH_FROM_WC, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_ah * ah; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_destroy_ah_t; + +int ibv_destroy_ah(struct ibv_ah * ah) { + uhyve_ibv_destroy_ah_t uhyve_args; + uhyve_args->ah = (struct ibv_ah *) virt_to_phys((size_t) ah); + uhyve_send(UHYVE_PORT_IBV_DESTROY_AH, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + const union ibv_gid * gid; + uint16_t lid; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_attach_mcast_t; + +int ibv_attach_mcast(struct ibv_qp * qp, const union ibv_gid * gid, uint16_t lid) { + uhyve_ibv_attach_mcast_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->gid = (const union ibv_gid *) virt_to_phys((size_t) gid); + uhyve_args->lid = lid; + uhyve_send(UHYVE_PORT_IBV_ATTACH_MCAST, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_qp * qp; + const union ibv_gid * gid; + uint16_t lid; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_detach_mcast_t; + +int ibv_detach_mcast(struct ibv_qp * qp, const union ibv_gid * gid, uint16_t lid) { + uhyve_ibv_detach_mcast_t uhyve_args; + uhyve_args->qp = (struct ibv_qp *) virt_to_phys((size_t) qp); + uhyve_args->gid = (const union ibv_gid *) virt_to_phys((size_t) gid); + uhyve_args->lid = lid; + uhyve_send(UHYVE_PORT_IBV_DETACH_MCAST, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + ; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_fork_init_t; + +int ibv_fork_init() { + uhyve_ibv_fork_init_t uhyve_args; + uhyve_args-> = ; + uhyve_send(UHYVE_PORT_IBV_FORK_INIT, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + enum ibv_node_type node_type; + // Return value: + const char * ret; +} __attribute__((packed)) uhyve_ibv_node_type_str_t; + +const char * ibv_node_type_str(enum ibv_node_type node_type) { + uhyve_ibv_node_type_str_t uhyve_args; + uhyve_args->node_type = node_type; + uhyve_args->ret = kmalloc(sizeof(const char)); + uhyve_send(UHYVE_PORT_IBV_NODE_TYPE_STR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + enum ibv_port_state port_state; + // Return value: + const char * ret; +} __attribute__((packed)) uhyve_ibv_port_state_str_t; + +const char * ibv_port_state_str(enum ibv_port_state port_state) { + uhyve_ibv_port_state_str_t uhyve_args; + uhyve_args->port_state = port_state; + uhyve_args->ret = kmalloc(sizeof(const char)); + uhyve_send(UHYVE_PORT_IBV_PORT_STATE_STR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + enum ibv_event_type event; + // Return value: + const char * ret; +} __attribute__((packed)) uhyve_ibv_event_type_str_t; + +const char * ibv_event_type_str(enum ibv_event_type event) { + uhyve_ibv_event_type_str_t uhyve_args; + uhyve_args->event = event; + uhyve_args->ret = kmalloc(sizeof(const char)); + uhyve_send(UHYVE_PORT_IBV_EVENT_TYPE_STR, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + struct ibv_context * context; + struct ibv_ah_attr * attr; + uint8_t [6] eth_mac; + uint16_t * vid; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_resolve_eth_l2_from_gid_t; + +int ibv_resolve_eth_l2_from_gid(struct ibv_context * context, struct ibv_ah_attr * attr, uint8_t [6] eth_mac, uint16_t * vid) { + uhyve_ibv_resolve_eth_l2_from_gid_t uhyve_args; + uhyve_args->context = (struct ibv_context *) virt_to_phys((size_t) context); + uhyve_args->attr = (struct ibv_ah_attr *) virt_to_phys((size_t) attr); + uhyve_args->eth_mac = eth_mac; + uhyve_args->vid = (uint16_t *) virt_to_phys((size_t) vid); + uhyve_send(UHYVE_PORT_IBV_RESOLVE_ETH_L2_FROM_GID, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + +typedef struct { + // Parameters: + uint32_t caps; + enum ibv_qp_type qpt; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_is_qpt_supported_t; + +int ibv_is_qpt_supported(uint32_t caps, enum ibv_qp_type qpt) { + uhyve_ibv_is_qpt_supported_t uhyve_args; + uhyve_args->caps = caps; + uhyve_args->qpt = qpt; + uhyve_send(UHYVE_PORT_IBV_IS_QPT_SUPPORTED, (unsigned) virt_to_phys((size_t) &uhyve_args)); + + // TODO: Fix pointers in returned data structures. + return uhyve_args.ret; +} + + diff --git a/tools/ibv_code_generator/kernel_api.py b/tools/ibv_code_generator/kernel_api.py new file mode 100755 index 000000000..b0f90a4b0 --- /dev/null +++ b/tools/ibv_code_generator/kernel_api.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +"""Copyright (c) 2017, Annika Wierichs, RWTH Aachen University + +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +TODO: Documentation""" + +src_file_path = 'function_prototypes.txt' + +ibv_gen_path = 'ibv_gen.c' +uhyve_cases_gen_path = 'uhyve_gen.c' + +with open(src_file_path, 'r') as f_src: + with open(ibv_gen_path, 'w') as f_ibv, open(uhyve_cases_gen_path, 'w') as f_uhyve: + # TODO: next: generate hyve stuff. + for line in f_src: + parens_split = line.split('(') + + ret_and_name = parens_split[0].split(' ') + function_name = ret_and_name[-1] + ret = ' '.join(ret_and_name[:-1]) + + all_params = parens_split[-1][:-1] + params = all_params.split(',') + params[-1] = params[-1][:-1] + + # Struct + struct_name = 'uhyve_{0}_t'.format(function_name) + f_ibv.write('typedef struct {\n') + if params: + f_ibv.write('\t// Parameters:\n') + for param in params: + f_ibv.write('\t{0};\n'.format(param)) + + if ret is not "void": + f_ibv.write('\t// Return value:\n') + f_ibv.write('\t{0} ret;\n'.format(ret)) + + f_ibv.write('}} __attribute__((packed)) {0};\n\n'.format(struct_name)) + + # Function + params_single_string = ', '.join(params) + f_ibv.write('{0} {1}({2}) {{\n'.format(ret, function_name, + params_single_string)) + + # Create uhyve_args and define parameters + f_ibv.write('\t{0} uhyve_args;\n'.format(struct_name)) + for param in params: + param_split = param.split(' ') + param_type = ' '.join(param_split[:-1]) + param_name = param_split[-1] + # Define struct members according to their type. + if '**' in param_type: + f_ibv.write('\t// TODO: Take care of ** parameter.\n') + elif '*' in param_type: + f_ibv.write('\tuhyve_args->{0} = ({1}) virt_to_phys((size_t) {2});\n' + .format(param_name, param_type, param_name)) + else: + f_ibv.write('\tuhyve_args->{0} = {0};\n'.format(param_name)) + + # Allocate memory for return value if it is a pointer. + if '**' in ret: + f_ibv.write('\n\t// TODO: Take care of return value.\n') + elif '*' in ret: + f_ibv.write('\n\tuhyve_args->ret = kmalloc(sizeof({0}));\n'.format(ret[:-2])) + + # call uhyve_send() using the respective port ID. + port_name = 'UHYVE_PORT_' + function_name.upper() + f_ibv.write('\n\tuhyve_send({0}, (unsigned) virt_to_phys((size_t) ' + '&uhyve_args));\n\n'.format(port_name)) + + f_ibv.write('\t// TODO: Fix pointers in returned data structures.\n') + + f_ibv.write('\treturn uhyve_args.ret;\n') + f_ibv.write('}\n\n\n') + + with open(uhyve_cases_gen_path, 'w') as f_ibv: + + + +# typedef struct { + # // Parameters: + # struct ibv_device *device; + # // Return value: + # struct ibv_context *ret; +# } __attribute__((packed)) uhyve_ibv_open_device_t; + +# int ibv_open_device(struct ibv_device *device) { + # uhyve_ibv_open_device_t uhyve_args; + # uhyve_args.device = (struct ibv_device *) virt_to_phys((size_t) device); + # uhyve_args->ret = kmalloc(sizeof(struct ibv_context)); + + # uhyve_send(UHYVE_PORT_IBV_OPEN_DEVICE, (unsigned)virt_to_phys((size_t) &uhyve_args)); + + # // Set all pointers contained in returned data structure to valid kernel space addresses. + # uhyve_args->ret->device = device; + + # return uhyve_args.ret; +# } diff --git a/tools/ibv_code_generator/uhyve_handler.py b/tools/ibv_code_generator/uhyve_handler.py new file mode 100644 index 000000000..e69de29bb diff --git a/tools/uhyve-ibv.h b/tools/uhyve-ibv.h index e6ff46616..de15ceacd 100644 --- a/tools/uhyve-ibv.h +++ b/tools/uhyve-ibv.h @@ -26,6 +26,15 @@ typedef enum { UHYVE_PORT_IBV_GET_DEVICE_LIST = 0x510, UHYVE_PORT_IBV_GET_DEVICE_NAME = 0x511, + UHYVE_PORT_IBV_OPEN_DEVICE = 0x512, + UHYVE_PORT_IBV_CREATE_COMP_CHANNEL = 0x513, + UHYVE_PORT_IBV_ALLOC_PD = 0x514, + UHYVE_PORT_IBV_REG_MR = 0x515, + UHYVE_PORT_IBV_CREATE_CQ = 0x516, + UHYVE_PORT_IBV_CREATE_QP = 0x517, + UHYVE_PORT_IBV_QUERY_QP = 0x518, + UHYVE_PORT_IBV_MODIFY_QP = 0x519, + //UHYVE_PORT_IBV_CREATE_AH = 0x520, } uhyve_ibv_t; typedef struct { @@ -38,9 +47,26 @@ typedef struct { } __attribute__((packed)) uhyve_ibv_get_device_list_t; typedef struct { - struct ibv_device *device; - char *ret; -} __attribute__((packed)) uhyve_ibv_get_device_name_t; + // Parameters: + struct ibv_qp *qp; + struct ibv_qp_attr *attr; + int attr_mask; + // Return value: + int ret; +} __attribute__((packed)) uhyve_ibv_modify_qp_t; + +typedef struct { + // Parameters: + struct ibv_pd *pd; + struct ibv_ah_attr *attr; + // Return value: + struct ibv_ah *ret; +} __attribute__((packed)) uhyve_ibv_create_ah_t; + +//typedef struct { + //struct ibv_device *device; + //char *ret; +//} __attribute__((packed)) uhyve_ibv_get_device_name_t; #endif // UHYVE_IBV_H diff --git a/tools/uhyve.c b/tools/uhyve.c index 8a4ca8b1b..5c85a40ca 100644 --- a/tools/uhyve.c +++ b/tools/uhyve.c @@ -979,6 +979,37 @@ static int vcpu_loop(void) // Copy number of devices to kernel memory memcpy(guest_mem+(size_t)args->num_devices, &num_devices, sizeof(num_devices)); + for (int d = 0; d < num_devices; d++) { + printf("uhyve.c: before memcpy list[d].\n"); + // Copy array entry containing ibv_device struct to kernel memory + memcpy(guest_mem + (size_t)args->dev_phys_ptr_list[d], temp_dev_list[d], sizeof(struct ibv_device)); + } + break; + } + + case UHYVE_PORT_IBV_OPEN_DEVICE: { + unsigned data = *((unsigned*)((size_t)run+run->io.data_offset)); + uhyve_ibv_open_device_t* args = (uhyve_ibv_open_device_t*) (guest_mem+data); + + struct ibv_context* context = ibv_open_device(guest_mem+(size_t)args->device); + + // Copy return value to memory location allocated in kernel space. + memcpy(guest_mem+(size_t)args->ret, context, sizeof(context)); + + break; + } + + case UHYVE_PORT_IBV_MODIFY_QP: { + unsigned data = *((unsigned*)((size_t)run+run->io.data_offset)); + uhyve_ibv_get_device_list_t* args = (uhyve_ibv_get_device_list_t*) (guest_mem+data); + + // Call IBV function from hypervisor + int num_devices; + struct ibv_device **temp_dev_list = ibv_get_device_list(&num_devices); + + // Copy number of devices to kernel memory + memcpy(guest_mem+(size_t)args->num_devices, &num_devices, sizeof(num_devices)); + for (int d = 0; d < num_devices; d++) { // TODO switch to num devices printf("uhyve.c: before memcpy list[d].\n"); // Copy array entry containing ibv_device struct to kernel memory @@ -987,15 +1018,34 @@ static int vcpu_loop(void) break; } - case UHYVE_PORT_IBV_GET_DEVICE_NAME: { + case UHYVE_PORT_IBV_CREATE_AH: { unsigned data = *((unsigned*)((size_t)run+run->io.data_offset)); - uhyve_ibv_get_device_name_t* args = (uhyve_ibv_get_device_name_t*) (guest_mem+data); + uhyve_ibv_get_device_list_t* args = (uhyve_ibv_get_device_list_t*) (guest_mem+data); - args->ret = ibv_get_device_name((struct ibv_device*)(guest_mem+(size_t)args->device)); - printf("UHYVE_PORT_IBV_GET_DEVICE_NAME\n"); + // Call IBV function from hypervisor + int num_devices; + struct ibv_device **temp_dev_list = ibv_get_device_list(&num_devices); + + // Copy number of devices to kernel memory + memcpy(guest_mem+(size_t)args->num_devices, &num_devices, sizeof(num_devices)); + + for (int d = 0; d < num_devices; d++) { // TODO switch to num devices + printf("uhyve.c: before memcpy list[d].\n"); + // Copy array entry containing ibv_device struct to kernel memory + memcpy(guest_mem + (size_t)args->dev_phys_ptr_list[d], temp_dev_list[d], sizeof(struct ibv_device)); + } break; } + /*case UHYVE_PORT_IBV_GET_DEVICE_NAME: {*/ + /*unsigned data = *((unsigned*)((size_t)run+run->io.data_offset));*/ + /*uhyve_ibv_get_device_name_t* args = (uhyve_ibv_get_device_name_t*) (guest_mem+data);*/ + + /*args->ret = ibv_get_device_name((struct ibv_device*)(guest_mem+(size_t)args->device));*/ + /*printf("UHYVE_PORT_IBV_GET_DEVICE_NAME\n");*/ + /*break;*/ + /*}*/ + default: err(1, "KVM: unhandled KVM_EXIT_IO at port 0x%x, direction %d\n", run->io.port, run->io.direction); break; diff --git a/usr/tests/CMakeLists.txt b/usr/tests/CMakeLists.txt index 0789e72cc..31aa3602b 100644 --- a/usr/tests/CMakeLists.txt +++ b/usr/tests/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(hellof hellof.f90) add_executable(pi pi.go) add_executable(ib-test ib_test.c) +#add_executable(ib-pingpong ib/pingpong.c ib/pingpong.h ib/pingpong_ud.c) #target_link_libraries(ib-test ibverbs) add_executable(test-malloc test-malloc.c) diff --git a/usr/tests/ib/pingpong.c b/usr/tests/ib/pingpong.c new file mode 100644 index 000000000..f47be7334 --- /dev/null +++ b/usr/tests/ib/pingpong.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2006 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "pingpong.h" + +#include // TODO +#include +#include +#include + +enum ibv_mtu pp_mtu_to_enum(int mtu) +{ + switch (mtu) { + case 256: return IBV_MTU_256; + case 512: return IBV_MTU_512; + case 1024: return IBV_MTU_1024; + case 2048: return IBV_MTU_2048; + case 4096: return IBV_MTU_4096; + default: return 0; + } +} + +int pp_get_port_info(struct ibv_context *context, int port, + struct ibv_port_attr *attr) +{ + return ibv_query_port(context, port, attr); +} + +void wire_gid_to_gid(const char *wgid, union ibv_gid *gid) +{ + char tmp[9]; + __be32 v32; + int i; + uint32_t tmp_gid[4]; + + for (tmp[8] = 0, i = 0; i < 4; ++i) { + memcpy(tmp, wgid + i * 8, 8); + sscanf(tmp, "%x", &v32); + tmp_gid[i] = be32toh(v32); + } + memcpy(gid, tmp_gid, sizeof(*gid)); +} + +void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]) +{ + uint32_t tmp_gid[4]; + int i; + + memcpy(tmp_gid, gid, sizeof(tmp_gid)); + for (i = 0; i < 4; ++i) + sprintf(&wgid[i * 8], "%08x", htobe32(tmp_gid[i])); +} diff --git a/usr/tests/ib/pingpong.h b/usr/tests/ib/pingpong.h new file mode 100644 index 000000000..2f5b3eea9 --- /dev/null +++ b/usr/tests/ib/pingpong.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2006 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +enum ibv_mtu pp_mtu_to_enum(int mtu); +int pp_get_port_info(struct ibv_context *context, int port, struct ibv_port_attr *attr); +void wire_gid_to_gid(const char *wgid, union ibv_gid *gid); +void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]); diff --git a/usr/tests/ib/pingpong_ud.c b/usr/tests/ib/pingpong_ud.c new file mode 100644 index 000000000..6648ebcea --- /dev/null +++ b/usr/tests/ib/pingpong_ud.c @@ -0,0 +1,861 @@ +/* + * Copyright (c) 2005 Topspin Communications. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pingpong.h" + +enum { + PINGPONG_RECV_WRID = 1, + PINGPONG_SEND_WRID = 2, +}; + +static int page_size; + +struct pingpong_context { + struct ibv_context *context; + struct ibv_comp_channel *channel; + struct ibv_pd *pd; + struct ibv_mr *mr; + struct ibv_cq *cq; + struct ibv_qp *qp; + struct ibv_ah *ah; + void *buf; + int size; + int send_flags; + int rx_depth; + int pending; + struct ibv_port_attr portinfo; +}; + +struct pingpong_dest { + int lid; + int qpn; + int psn; + union ibv_gid gid; +}; + +static int pp_connect_ctx(struct pingpong_context *ctx, int port, int my_psn, + int sl, struct pingpong_dest *dest, int sgid_idx) +{ + struct ibv_ah_attr ah_attr = { + .is_global = 0, + .dlid = dest->lid, + .sl = sl, + .src_path_bits = 0, + .port_num = port + }; + struct ibv_qp_attr attr = { + .qp_state = IBV_QPS_RTR + }; + + if (ibv_modify_qp(ctx->qp, &attr, IBV_QP_STATE)) { + fprintf(stderr, "Failed to modify QP to RTR\n"); + return 1; + } + + attr.qp_state = IBV_QPS_RTS; + attr.sq_psn = my_psn; + + if (ibv_modify_qp(ctx->qp, &attr, + IBV_QP_STATE | + IBV_QP_SQ_PSN)) { + fprintf(stderr, "Failed to modify QP to RTS\n"); + return 1; + } + + if (dest->gid.global.interface_id) { + ah_attr.is_global = 1; + ah_attr.grh.hop_limit = 1; + ah_attr.grh.dgid = dest->gid; + ah_attr.grh.sgid_index = sgid_idx; + } + + ctx->ah = ibv_create_ah(ctx->pd, &ah_attr); + if (!ctx->ah) { + fprintf(stderr, "Failed to create AH\n"); + return 1; + } + + return 0; +} + +static struct pingpong_dest *pp_client_exch_dest(const char *servername, int port, + const struct pingpong_dest *my_dest) +{ + struct addrinfo *res, *t; + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM + }; + char *service; + char msg[sizeof "0000:000000:000000:00000000000000000000000000000000"]; + int n; + int sockfd = -1; + struct pingpong_dest *rem_dest = NULL; + char gid[33]; + + if (asprintf(&service, "%d", port) < 0) + return NULL; + + n = getaddrinfo(servername, service, &hints, &res); + + if (n < 0) { + fprintf(stderr, "%s for %s:%d\n", gai_strerror(n), servername, port); + free(service); + return NULL; + } + + for (t = res; t; t = t->ai_next) { + sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol); + if (sockfd >= 0) { + if (!connect(sockfd, t->ai_addr, t->ai_addrlen)) + break; + close(sockfd); + sockfd = -1; + } + } + + freeaddrinfo(res); + free(service); + + if (sockfd < 0) { + fprintf(stderr, "Couldn't connect to %s:%d\n", servername, port); + return NULL; + } + + gid_to_wire_gid(&my_dest->gid, gid); + sprintf(msg, "%04x:%06x:%06x:%s", my_dest->lid, my_dest->qpn, + my_dest->psn, gid); + if (write(sockfd, msg, sizeof msg) != sizeof msg) { + fprintf(stderr, "Couldn't send local address\n"); + goto out; + } + + if (read(sockfd, msg, sizeof msg) != sizeof msg || + write(sockfd, "done", sizeof "done") != sizeof "done") { + perror("client read/write"); + fprintf(stderr, "Couldn't read/write remote address\n"); + goto out; + } + + rem_dest = malloc(sizeof *rem_dest); + if (!rem_dest) + goto out; + + sscanf(msg, "%x:%x:%x:%s", &rem_dest->lid, &rem_dest->qpn, + &rem_dest->psn, gid); + wire_gid_to_gid(gid, &rem_dest->gid); + +out: + close(sockfd); + return rem_dest; +} + +static struct pingpong_dest *pp_server_exch_dest(struct pingpong_context *ctx, + int ib_port, int port, int sl, + const struct pingpong_dest *my_dest, + int sgid_idx) +{ + struct addrinfo *res, *t; + struct addrinfo hints = { + .ai_flags = AI_PASSIVE, + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM + }; + char *service; + char msg[sizeof "0000:000000:000000:00000000000000000000000000000000"]; + int n; + int sockfd = -1, connfd; + struct pingpong_dest *rem_dest = NULL; + char gid[33]; + + if (asprintf(&service, "%d", port) < 0) + return NULL; + + n = getaddrinfo(NULL, service, &hints, &res); + + if (n < 0) { + fprintf(stderr, "%s for port %d\n", gai_strerror(n), port); + free(service); + return NULL; + } + + for (t = res; t; t = t->ai_next) { + sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol); + if (sockfd >= 0) { + n = 1; + + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n); + + if (!bind(sockfd, t->ai_addr, t->ai_addrlen)) + break; + close(sockfd); + sockfd = -1; + } + } + + freeaddrinfo(res); + free(service); + + if (sockfd < 0) { + fprintf(stderr, "Couldn't listen to port %d\n", port); + return NULL; + } + + listen(sockfd, 1); + connfd = accept(sockfd, NULL, NULL); + close(sockfd); + if (connfd < 0) { + fprintf(stderr, "accept() failed\n"); + return NULL; + } + + n = read(connfd, msg, sizeof msg); + if (n != sizeof msg) { + perror("server read"); + fprintf(stderr, "%d/%d: Couldn't read remote address\n", n, (int) sizeof msg); + goto out; + } + + rem_dest = malloc(sizeof *rem_dest); + if (!rem_dest) + goto out; + + sscanf(msg, "%x:%x:%x:%s", &rem_dest->lid, &rem_dest->qpn, + &rem_dest->psn, gid); + wire_gid_to_gid(gid, &rem_dest->gid); + + if (pp_connect_ctx(ctx, ib_port, my_dest->psn, sl, rem_dest, + sgid_idx)) { + fprintf(stderr, "Couldn't connect to remote QP\n"); + free(rem_dest); + rem_dest = NULL; + goto out; + } + + gid_to_wire_gid(&my_dest->gid, gid); + sprintf(msg, "%04x:%06x:%06x:%s", my_dest->lid, my_dest->qpn, + my_dest->psn, gid); + if (write(connfd, msg, sizeof msg) != sizeof msg || + read(connfd, msg, sizeof msg) != sizeof "done") { + fprintf(stderr, "Couldn't send/recv local address\n"); + free(rem_dest); + rem_dest = NULL; + goto out; + } +out: + close(connfd); + return rem_dest; +} + +static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, + int rx_depth, int port, + int use_event) +{ + struct pingpong_context *ctx; + + ctx = malloc(sizeof *ctx); + if (!ctx) + return NULL; + + ctx->size = size; + ctx->send_flags = IBV_SEND_SIGNALED; + ctx->rx_depth = rx_depth; + + ctx->buf = memalign(page_size, size + 40); + if (!ctx->buf) { + fprintf(stderr, "Couldn't allocate work buf.\n"); + goto clean_ctx; + } + + /* FIXME memset(ctx->buf, 0, size + 40); */ + memset(ctx->buf, 0x7b, size + 40); + + ctx->context = ibv_open_device(ib_dev); + if (!ctx->context) { + fprintf(stderr, "Couldn't get context for %s\n", + ibv_get_device_name(ib_dev)); + goto clean_buffer; + } + + { + struct ibv_port_attr port_info = {}; + int mtu; + + if (ibv_query_port(ctx->context, port, &port_info)) { + fprintf(stderr, "Unable to query port info for port %d\n", port); + goto clean_device; + } + mtu = 1 << (port_info.active_mtu + 7); + if (size > mtu) { + fprintf(stderr, "Requested size larger than port MTU (%d)\n", mtu); + goto clean_device; + } + } + + if (use_event) { + ctx->channel = ibv_create_comp_channel(ctx->context); + if (!ctx->channel) { + fprintf(stderr, "Couldn't create completion channel\n"); + goto clean_device; + } + } else + ctx->channel = NULL; + + ctx->pd = ibv_alloc_pd(ctx->context); + if (!ctx->pd) { + fprintf(stderr, "Couldn't allocate PD\n"); + goto clean_comp_channel; + } + + ctx->mr = ibv_reg_mr(ctx->pd, ctx->buf, size + 40, IBV_ACCESS_LOCAL_WRITE); + if (!ctx->mr) { + fprintf(stderr, "Couldn't register MR\n"); + goto clean_pd; + } + + ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL, + ctx->channel, 0); + if (!ctx->cq) { + fprintf(stderr, "Couldn't create CQ\n"); + goto clean_mr; + } + + { + struct ibv_qp_attr attr; + struct ibv_qp_init_attr init_attr = { + .send_cq = ctx->cq, + .recv_cq = ctx->cq, + .cap = { + .max_send_wr = 1, + .max_recv_wr = rx_depth, + .max_send_sge = 1, + .max_recv_sge = 1 + }, + .qp_type = IBV_QPT_UD, + }; + + ctx->qp = ibv_create_qp(ctx->pd, &init_attr); + if (!ctx->qp) { + fprintf(stderr, "Couldn't create QP\n"); + goto clean_cq; + } + + ibv_query_qp(ctx->qp, &attr, IBV_QP_CAP, &init_attr); + if (init_attr.cap.max_inline_data >= size) { + ctx->send_flags |= IBV_SEND_INLINE; + } + } + + { + struct ibv_qp_attr attr = { + .qp_state = IBV_QPS_INIT, + .pkey_index = 0, + .port_num = port, + .qkey = 0x11111111 + }; + + if (ibv_modify_qp(ctx->qp, &attr, + IBV_QP_STATE | + IBV_QP_PKEY_INDEX | + IBV_QP_PORT | + IBV_QP_QKEY)) { + fprintf(stderr, "Failed to modify QP to INIT\n"); + goto clean_qp; + } + } + + return ctx; + +clean_qp: + ibv_destroy_qp(ctx->qp); + +clean_cq: + ibv_destroy_cq(ctx->cq); + +clean_mr: + ibv_dereg_mr(ctx->mr); + +clean_pd: + ibv_dealloc_pd(ctx->pd); + +clean_comp_channel: + if (ctx->channel) + ibv_destroy_comp_channel(ctx->channel); + +clean_device: + ibv_close_device(ctx->context); + +clean_buffer: + free(ctx->buf); + +clean_ctx: + free(ctx); + + return NULL; +} + +static int pp_close_ctx(struct pingpong_context *ctx) +{ + if (ibv_destroy_qp(ctx->qp)) { + fprintf(stderr, "Couldn't destroy QP\n"); + return 1; + } + + if (ibv_destroy_cq(ctx->cq)) { + fprintf(stderr, "Couldn't destroy CQ\n"); + return 1; + } + + if (ibv_dereg_mr(ctx->mr)) { + fprintf(stderr, "Couldn't deregister MR\n"); + return 1; + } + + if (ibv_destroy_ah(ctx->ah)) { + fprintf(stderr, "Couldn't destroy AH\n"); + return 1; + } + + if (ibv_dealloc_pd(ctx->pd)) { + fprintf(stderr, "Couldn't deallocate PD\n"); + return 1; + } + + if (ctx->channel) { + if (ibv_destroy_comp_channel(ctx->channel)) { + fprintf(stderr, "Couldn't destroy completion channel\n"); + return 1; + } + } + + if (ibv_close_device(ctx->context)) { + fprintf(stderr, "Couldn't release context\n"); + return 1; + } + + free(ctx->buf); + free(ctx); + + return 0; +} + +static int pp_post_recv(struct pingpong_context *ctx, int n) +{ + struct ibv_sge list = { + .addr = (uintptr_t) ctx->buf, + .length = ctx->size + 40, + .lkey = ctx->mr->lkey + }; + struct ibv_recv_wr wr = { + .wr_id = PINGPONG_RECV_WRID, + .sg_list = &list, + .num_sge = 1, + }; + struct ibv_recv_wr *bad_wr; + int i; + + for (i = 0; i < n; ++i) + if (ibv_post_recv(ctx->qp, &wr, &bad_wr)) + break; + + return i; +} + +static int pp_post_send(struct pingpong_context *ctx, uint32_t qpn) +{ + struct ibv_sge list = { + .addr = (uintptr_t) ctx->buf + 40, + .length = ctx->size, + .lkey = ctx->mr->lkey + }; + struct ibv_send_wr wr = { + .wr_id = PINGPONG_SEND_WRID, + .sg_list = &list, + .num_sge = 1, + .opcode = IBV_WR_SEND, + .send_flags = ctx->send_flags, + .wr = { + .ud = { + .ah = ctx->ah, + .remote_qpn = qpn, + .remote_qkey = 0x11111111 + } + } + }; + struct ibv_send_wr *bad_wr; + + return ibv_post_send(ctx->qp, &wr, &bad_wr); +} + +static void usage(const char *argv0) +{ + printf("Usage:\n"); + printf(" %s start a server and wait for connection\n", argv0); + printf(" %s connect to server at \n", argv0); + printf("\n"); + printf("Options:\n"); + printf(" -p, --port= listen on/connect to port (default 18515)\n"); + printf(" -d, --ib-dev= use IB device (default first device found)\n"); + printf(" -i, --ib-port= use port of IB device (default 1)\n"); + printf(" -s, --size= size of message to exchange (default 2048)\n"); + printf(" -r, --rx-depth= number of receives to post at a time (default 500)\n"); + printf(" -n, --iters= number of exchanges (default 1000)\n"); + printf(" -l, --sl= send messages with service level (default 0)\n"); + printf(" -e, --events sleep on CQ events (default poll)\n"); + printf(" -g, --gid-idx= local port gid index\n"); +} + +int main(int argc, char *argv[]) +{ + struct ibv_device **dev_list; + struct ibv_device *ib_dev; + struct pingpong_context *ctx; + struct pingpong_dest my_dest; + struct pingpong_dest *rem_dest; + struct timeval start, end; + char *ib_devname = NULL; + char *servername = NULL; + unsigned int port = 18515; + int ib_port = 1; + unsigned int size = 2048; + unsigned int rx_depth = 500; + unsigned int iters = 1000; + int use_event = 0; + int routs; + int rcnt, scnt; + int num_cq_events = 0; + int sl = 0; + int gidx = -1; + char gid[33]; + + srand48(getpid() * time(NULL)); + + while (1) { + int c; + + static struct option long_options[] = { + { .name = "port", .has_arg = 1, .val = 'p' }, + { .name = "ib-dev", .has_arg = 1, .val = 'd' }, + { .name = "ib-port", .has_arg = 1, .val = 'i' }, + { .name = "size", .has_arg = 1, .val = 's' }, + { .name = "rx-depth", .has_arg = 1, .val = 'r' }, + { .name = "iters", .has_arg = 1, .val = 'n' }, + { .name = "sl", .has_arg = 1, .val = 'l' }, + { .name = "events", .has_arg = 0, .val = 'e' }, + { .name = "gid-idx", .has_arg = 1, .val = 'g' }, + {} + }; + + c = getopt_long(argc, argv, "p:d:i:s:r:n:l:eg:", + long_options, NULL); + if (c == -1) + break; + + switch (c) { + case 'p': + port = strtol(optarg, NULL, 0); + if (port > 65535) { + usage(argv[0]); + return 1; + } + break; + + case 'd': + ib_devname = strdupa(optarg); + break; + + case 'i': + ib_port = strtol(optarg, NULL, 0); + if (ib_port < 1) { + usage(argv[0]); + return 1; + } + break; + + case 's': + size = strtoul(optarg, NULL, 0); + break; + + case 'r': + rx_depth = strtoul(optarg, NULL, 0); + break; + + case 'n': + iters = strtoul(optarg, NULL, 0); + break; + + case 'l': + sl = strtol(optarg, NULL, 0); + break; + + case 'e': + ++use_event; + break; + + case 'g': + gidx = strtol(optarg, NULL, 0); + break; + + default: + usage(argv[0]); + return 1; + } + } + + if (optind == argc - 1) + servername = strdupa(argv[optind]); + else if (optind < argc) { + usage(argv[0]); + return 1; + } + + page_size = sysconf(_SC_PAGESIZE); + + dev_list = ibv_get_device_list(NULL); + if (!dev_list) { + perror("Failed to get IB devices list"); + return 1; + } + + if (!ib_devname) { + ib_dev = *dev_list; + if (!ib_dev) { + fprintf(stderr, "No IB devices found\n"); + return 1; + } + } else { + int i; + for (i = 0; dev_list[i]; ++i) + if (!strcmp(ibv_get_device_name(dev_list[i]), ib_devname)) + break; + ib_dev = dev_list[i]; + if (!ib_dev) { + fprintf(stderr, "IB device %s not found\n", ib_devname); + return 1; + } + } + + ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port, use_event); + if (!ctx) + return 1; + + routs = pp_post_recv(ctx, ctx->rx_depth); + if (routs < ctx->rx_depth) { + fprintf(stderr, "Couldn't post receive (%d)\n", routs); + return 1; + } + + if (use_event) + if (ibv_req_notify_cq(ctx->cq, 0)) { + fprintf(stderr, "Couldn't request CQ notification\n"); + return 1; + } + + if (pp_get_port_info(ctx->context, ib_port, &ctx->portinfo)) { + fprintf(stderr, "Couldn't get port info\n"); + return 1; + } + my_dest.lid = ctx->portinfo.lid; + + my_dest.qpn = ctx->qp->qp_num; + my_dest.psn = lrand48() & 0xffffff; + + if (gidx >= 0) { + if (ibv_query_gid(ctx->context, ib_port, gidx, &my_dest.gid)) { + fprintf(stderr, "Could not get local gid for gid index " + "%d\n", gidx); + return 1; + } + } else + memset(&my_dest.gid, 0, sizeof my_dest.gid); + + inet_ntop(AF_INET6, &my_dest.gid, gid, sizeof gid); + printf(" local address: LID 0x%04x, QPN 0x%06x, PSN 0x%06x: GID %s\n", + my_dest.lid, my_dest.qpn, my_dest.psn, gid); + + if (servername) + rem_dest = pp_client_exch_dest(servername, port, &my_dest); + else + rem_dest = pp_server_exch_dest(ctx, ib_port, port, sl, + &my_dest, gidx); + + if (!rem_dest) + return 1; + + inet_ntop(AF_INET6, &rem_dest->gid, gid, sizeof gid); + printf(" remote address: LID 0x%04x, QPN 0x%06x, PSN 0x%06x, GID %s\n", + rem_dest->lid, rem_dest->qpn, rem_dest->psn, gid); + + if (servername) + if (pp_connect_ctx(ctx, ib_port, my_dest.psn, sl, rem_dest, + gidx)) + return 1; + + ctx->pending = PINGPONG_RECV_WRID; + + if (servername) { + if (pp_post_send(ctx, rem_dest->qpn)) { + fprintf(stderr, "Couldn't post send\n"); + return 1; + } + ctx->pending |= PINGPONG_SEND_WRID; + } + + if (gettimeofday(&start, NULL)) { + perror("gettimeofday"); + return 1; + } + + rcnt = scnt = 0; + while (rcnt < iters || scnt < iters) { + if (use_event) { + struct ibv_cq *ev_cq; + void *ev_ctx; + + if (ibv_get_cq_event(ctx->channel, &ev_cq, &ev_ctx)) { + fprintf(stderr, "Failed to get cq_event\n"); + return 1; + } + + ++num_cq_events; + + if (ev_cq != ctx->cq) { + fprintf(stderr, "CQ event for unknown CQ %p\n", ev_cq); + return 1; + } + + if (ibv_req_notify_cq(ctx->cq, 0)) { + fprintf(stderr, "Couldn't request CQ notification\n"); + return 1; + } + } + + { + struct ibv_wc wc[2]; + int ne, i; + + do { + ne = ibv_poll_cq(ctx->cq, 2, wc); + if (ne < 0) { + fprintf(stderr, "poll CQ failed %d\n", ne); + return 1; + } + } while (!use_event && ne < 1); + + for (i = 0; i < ne; ++i) { + if (wc[i].status != IBV_WC_SUCCESS) { + fprintf(stderr, "Failed status %s (%d) for wr_id %d\n", + ibv_wc_status_str(wc[i].status), + wc[i].status, (int) wc[i].wr_id); + return 1; + } + + switch ((int) wc[i].wr_id) { + case PINGPONG_SEND_WRID: + ++scnt; + break; + + case PINGPONG_RECV_WRID: + if (--routs <= 1) { + routs += pp_post_recv(ctx, ctx->rx_depth - routs); + if (routs < ctx->rx_depth) { + fprintf(stderr, + "Couldn't post receive (%d)\n", + routs); + return 1; + } + } + + ++rcnt; + break; + + default: + fprintf(stderr, "Completion for unknown wr_id %d\n", + (int) wc[i].wr_id); + return 1; + } + + ctx->pending &= ~(int) wc[i].wr_id; + if (scnt < iters && !ctx->pending) { + if (pp_post_send(ctx, rem_dest->qpn)) { + fprintf(stderr, "Couldn't post send\n"); + return 1; + } + ctx->pending = PINGPONG_RECV_WRID | + PINGPONG_SEND_WRID; + } + } + } + } + + if (gettimeofday(&end, NULL)) { + perror("gettimeofday"); + return 1; + } + + { + float usec = (end.tv_sec - start.tv_sec) * 1000000 + + (end.tv_usec - start.tv_usec); + long long bytes = (long long) size * iters * 2; + + printf("%lld bytes in %.2f seconds = %.2f Mbit/sec\n", + bytes, usec / 1000000., bytes * 8. / usec); + printf("%d iters in %.2f seconds = %.2f usec/iter\n", + iters, usec / 1000000., usec / iters); + } + + ibv_ack_cq_events(ctx->cq, num_cq_events); + + if (pp_close_ctx(ctx)) + return 1; + + ibv_free_device_list(dev_list); + free(rem_dest); + + return 0; +} diff --git a/usr/tests/ib_test.c b/usr/tests/ib_test.c index dd0a0a139..7e86aedaa 100644 --- a/usr/tests/ib_test.c +++ b/usr/tests/ib_test.c @@ -52,7 +52,7 @@ int main(int argc, char** argv) int num_devices; printf("ib_test.c: before get dev list.\n"); - dev_list = h_ibv_get_device_list(&num_devices); + dev_list = ibv_get_device_list(&num_devices); printf("ib_test.c: after get dev list.\n"); printf("ib_test.c: num devices: %d\n", num_devices); @@ -67,7 +67,7 @@ int main(int argc, char** argv) /*}*/ /*printf("after dev list check.\n");*/ - /*const char* dev_name = h_ibv_get_device_name(dev_list[0]);*/ + /*const char* dev_name = ibv_get_device_name(dev_list[0]);*/ /*printf("after get device name.\n");*/ /*if (!dev_name) {*/