diff -Nru libibverbs-1.1.7/debian/changelog libibverbs-1.1.7/debian/changelog --- libibverbs-1.1.7/debian/changelog 2014-01-06 12:06:39.000000000 -0200 +++ libibverbs-1.1.7/debian/changelog 2015-08-05 16:14:20.000000000 -0300 @@ -1,3 +1,11 @@ +libibverbs (1.1.7-1ubuntu2) trusty; urgency=medium + + * Add general defitions to support uverbs extensions (LP: #1409904) + * Add receive flow steering support (LP: #1409904) + * Add checksum offload support capability (LP: #1409904) + + -- Rafael David Tinoco Wed, 05 Aug 2015 16:14:02 -0300 + libibverbs (1.1.7-1ubuntu1) trusty; urgency=medium * Merge with Debian; remaining changes: diff -Nru libibverbs-1.1.7/debian/patches/Add-checksum-offload-support-capability.patch libibverbs-1.1.7/debian/patches/Add-checksum-offload-support-capability.patch --- libibverbs-1.1.7/debian/patches/Add-checksum-offload-support-capability.patch 1969-12-31 21:00:00.000000000 -0300 +++ libibverbs-1.1.7/debian/patches/Add-checksum-offload-support-capability.patch 2015-08-03 11:42:01.000000000 -0300 @@ -0,0 +1,49 @@ +Description: Add checksum offload support capability flag + +Add a device capability flag IB_DEVICE_IP_SUM to denote checksum offload +support. Devices should set this flag if they support insertion of IP, TCP +and UDP checksums on outgoing IP packets sent over IB UD or ETH RAW_PACKET QPs. + +In addition add a send flag IBV_SEND_IP_CSUM to utilize this capability. + +Signed-off-by: Eyal Perry +Signed-off-by: Moshe Lazer +Signed-off-by: Or Gerlitz + +Origin: https://patchwork.kernel.org/patch/5572101/ +Bug-Ubuntu: https://launchpad.net/bugs/1409904 +Last-Update: 2015-02-09 + +--- libibverbs-1.1.7.orig/include/infiniband/verbs.h ++++ libibverbs-1.1.7/include/infiniband/verbs.h +@@ -110,6 +110,7 @@ enum ibv_device_cap_flags { + IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12, + IBV_DEVICE_SRQ_RESIZE = 1 << 13, + IBV_DEVICE_N_NOTIFY_CQ = 1 << 14, ++ IBV_DEVICE_IP_CSUM = 1 << 18, + IBV_DEVICE_MANAGED_FLOW_STEERING = 1 << 29 + }; + +@@ -542,7 +543,8 @@ enum ibv_send_flags { + IBV_SEND_FENCE = 1 << 0, + IBV_SEND_SIGNALED = 1 << 1, + IBV_SEND_SOLICITED = 1 << 2, +- IBV_SEND_INLINE = 1 << 3 ++ IBV_SEND_INLINE = 1 << 3, ++ IBV_SEND_IP_CSUM = 1 << 4 + }; + + struct ibv_sge { +--- libibverbs-1.1.7.orig/man/ibv_post_send.3 ++++ libibverbs-1.1.7/man/ibv_post_send.3 +@@ -98,6 +98,10 @@ The attribute send_flags describes the p + .TP + .B IBV_SEND_INLINE \fR Send data in given gather list as inline data + in a send WQE. Valid only for Send and RDMA Write. The L_Key will not be checked. ++.TP ++.B IBV_SEND_IP_CSUM \fR Offload the IP and TCP/UDP checksum calculation. ++Valid only for QPs with Transport Service Type \fBIBV_QPT_UD\fR or \fBIBV_QPT_RAW_PACKET\fR. ++This feature supported only when \fBIBV_DEVICE_IP_CSUM\fR the flag is set in the device capability flags. + .SH "RETURN VALUE" + .B ibv_post_send() + returns 0 on success, or the value of errno on failure (which indicates the failure reason). diff -Nru libibverbs-1.1.7/debian/patches/Add-general-definitions-to-support-uverbs-extensions.patch libibverbs-1.1.7/debian/patches/Add-general-definitions-to-support-uverbs-extensions.patch --- libibverbs-1.1.7/debian/patches/Add-general-definitions-to-support-uverbs-extensions.patch 1969-12-31 21:00:00.000000000 -0300 +++ libibverbs-1.1.7/debian/patches/Add-general-definitions-to-support-uverbs-extensions.patch 2015-08-03 11:42:01.000000000 -0300 @@ -0,0 +1,117 @@ +Description: Add general definitions to support uverbs extensions + +Each new verb using the verbs extensions approach includes an extended +header, containing: + + __u16 provider_in_words; + __u16 provider_out_words; + __u32 cmd_hdr_reserved; + __u32 comp_mask; + +The new macros IBV_INIT_CMD_EX() and IBV_INIT_CMD_RESP_EX() initialize +these fields. + +Author: Matan Barak +Signed-off-by: Matan Barak +Signed-off-by: Or Gerlitz +Signed-off-by: Roland Dreier + +Origin: upstream, commit: cbf2a35162afcc9e97870b7b18d6477133a8dfa2 +Bug-Ubuntu: https://launchpad.net/bugs/1409904 +Last-Update: 2014-02-09 + +--- libibverbs-1.1.7.orig/include/infiniband/kern-abi.h ++++ libibverbs-1.1.7/include/infiniband/kern-abi.h +@@ -48,6 +48,8 @@ + #define IB_USER_VERBS_MIN_ABI_VERSION 3 + #define IB_USER_VERBS_MAX_ABI_VERSION 6 + ++#define IB_USER_VERBS_CMD_THRESHOLD 50 ++ + enum { + IB_USER_VERBS_CMD_GET_CONTEXT, + IB_USER_VERBS_CMD_QUERY_DEVICE, +@@ -88,6 +90,14 @@ enum { + IB_USER_VERBS_CMD_POST_SRQ_RECV + }; + ++#define IB_USER_VERBS_CMD_COMMAND_MASK 0xff ++#define IB_USER_VERBS_CMD_FLAGS_MASK 0xff000000u ++#define IB_USER_VERBS_CMD_FLAGS_SHIFT 24 ++ ++ ++#define IB_USER_VERBS_CMD_FLAG_EXTENDED 0x80ul ++ ++ + /* + * Make sure that all structs defined in this file remain laid out so + * that they pack the same way on 32-bit and 64-bit architectures (to +@@ -99,6 +109,32 @@ enum { + * different between 32-bit and 64-bit architectures. + */ + ++struct hdr { ++ __u32 command; ++ __u16 in_words; ++ __u16 out_words; ++}; ++ ++struct response_hdr { ++ __u64 response; ++}; ++ ++struct ex_hdr { ++ struct { ++ __u32 command; ++ __u16 in_words; ++ __u16 out_words; ++ }; ++ struct { ++ __u64 response; ++ }; ++ struct { ++ __u16 provider_in_words; ++ __u16 provider_out_words; ++ __u32 reserved; ++ }; ++}; ++ + struct ibv_kern_async_event { + __u64 element; + __u32 event_type; +--- libibverbs-1.1.7.orig/src/ibverbs.h ++++ libibverbs-1.1.7/src/ibverbs.h +@@ -102,4 +102,33 @@ HIDDEN int ibverbs_init(struct ibv_devic + (cmd)->response = (uintptr_t) (out); \ + } while (0) + ++#define IBV_INIT_CMD_RESP_EX_V(cmd, cmd_size, size, opcode, out, resp_size,\ ++ outsize) \ ++ do { \ ++ size_t c_size = cmd_size - sizeof(struct ex_hdr); \ ++ if (abi_ver > 2) \ ++ (cmd)->hdr.command = IB_USER_VERBS_CMD_##opcode; \ ++ else \ ++ (cmd)->hdr.command = \ ++ IB_USER_VERBS_CMD_##opcode##_V2; \ ++ (cmd)->hdr.in_words = ((c_size) / 8); \ ++ (cmd)->hdr.out_words = ((resp_size) / 8); \ ++ (cmd)->hdr.provider_in_words = (((size) - (cmd_size))/8);\ ++ (cmd)->hdr.provider_out_words = \ ++ (((outsize) - (resp_size)) / 8); \ ++ (cmd)->hdr.response = (uintptr_t) (out); \ ++ (cmd)->hdr.reserved = 0; \ ++ } while (0) ++ ++#define IBV_INIT_CMD_RESP_EX_VCMD(cmd, cmd_size, size, opcode, out, outsize) \ ++ IBV_INIT_CMD_RESP_EX_V(cmd, cmd_size, size, opcode, out, \ ++ sizeof(*(out)), outsize) ++ ++#define IBV_INIT_CMD_RESP_EX(cmd, size, opcode, out, outsize) \ ++ IBV_INIT_CMD_RESP_EX_V(cmd, sizeof(*(cmd)), size, opcode, out, \ ++ sizeof(*(out)), outsize) ++ ++#define IBV_INIT_CMD_EX(cmd, size, opcode) \ ++ IBV_INIT_CMD_RESP_EX_V(cmd, sizeof(*(cmd)), size, opcode, NULL, 0, 0) ++ + #endif /* IB_VERBS_H */ diff -Nru libibverbs-1.1.7/debian/patches/Add-receive-flow-steering-support.patch libibverbs-1.1.7/debian/patches/Add-receive-flow-steering-support.patch --- libibverbs-1.1.7/debian/patches/Add-receive-flow-steering-support.patch 1969-12-31 21:00:00.000000000 -0300 +++ libibverbs-1.1.7/debian/patches/Add-receive-flow-steering-support.patch 2015-08-03 11:42:01.000000000 -0300 @@ -0,0 +1,524 @@ +Description: Add receive flow steering support + +The RDMA stack allows for applications to create IB_QPT_RAW_PACKET +QPs, which receive plain Ethernet packets -- specifically packets that +don't carry any QPN to be matched by the receiving side. Applications +using these QPs must be provided with a method to program some +steering rule into the HW so packets arriving at the local port can be +routed to them. + +In a similar manner, when the device supports flow streeing, IB UD QPs +created by IPoIB allow userspace applications to steer specific TCP/IP +flows to their QPs. + +This patch adds ibv_create_flow(), which allow providing a flow +specification for a QP. When there's a match between the +specification and a received packet, the packet is forwarded to that +QP, in a the same way one uses ibv_attach_mcast() for IB UD multicast +handling. + +Flow specifications are provided as instances of struct +ibv_flow_spec_yyy, which describes L2, L3 and L4 headers. Currently +specs for Ethernet, IPv4, TCP and UDP are defined. Flow specs are +made of values and masks. + +The input to ib_create_flow() is a struct ib_flow_attr, which contains +a few mandatory control elements and optional flow specs. + + struct ibv_flow_attr { + uint32_t comp_mask; + enum ibv_flow_attr_type type; + uint16_t size; + uint16_t priority; + uint8_t num_of_specs; + uint8_t port; + uint32_t flags; + /* Following are the optional layers according to user request + * struct ibv_flow_spec_xxx [L2] + * struct ibv_flow_spec_yyy [L3/L4] + */ + }; + +These flow specs are defined and used in a way which allows adding new +spec types without kernel/user ABI change, just with a little API +enhancement which defines the newly added spec. + +The flow spec structures are defined with TLV (Type-Length-Value) +entries, which allows calling ib_create_flow() with a list of variable +length of optional specs. + +For the actual processing of ibv_flow_attr the kernel uses the number +of specs and the size mandatory fields along with the TLV nature of +the specs. + +The returned value from ibv_create_flow() is a struct ibv_flow, which +contains a handle provided by the kernel to be used when calling +ibv_destroy_flow(). + +The ib_flow_attr enum type supports usage of flow steering for +promiscuous and sniffer purposes: + + IBV_FLOW_ATTR_NORMAL - "regular" rule, steering according to rule + specification + + IBV_FLOW_ATTR_ALL_DEFAULT - default unicast and multicast rule, + receive all Ethernet traffic which isn't steered to any QP + + IBV_FLOW_ATTR_MC_DEFAULT - same as IB_FLOW_ATTR_ALL_DEFAULT but + only for multicast + +ALL_DEFAULT and MC_DEFAULT rules options are valid only for Ethernet +link type. + +Author: Or Gerlitz +Signed-off-by: Hadar Hen Zion +Signed-off-by: Or Gerlitz +Signed-off-by: Matan Barak +Signed-off-by: Roland Dreier + +Origin: upstream, commit: 389de6a6ef4ed90615629a9eed7f9f17bedf47e3 +Bug-Ubuntu: https://launchpad.net/bugs/1409904 +Last-Update: 2015-02-09 + +--- libibverbs-1.1.7.orig/include/infiniband/driver.h ++++ libibverbs-1.1.7/include/infiniband/driver.h +@@ -135,6 +135,10 @@ int ibv_cmd_destroy_ah(struct ibv_ah *ah + int ibv_cmd_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid); + int ibv_cmd_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid); + ++struct ibv_flow *ibv_cmd_create_flow(struct ibv_qp *qp, ++ struct ibv_flow_attr *flow_attr); ++int ibv_cmd_destroy_flow(struct ibv_flow *flow_id); ++ + int ibv_dontfork_range(void *base, size_t size); + int ibv_dofork_range(void *base, size_t size); + +--- libibverbs-1.1.7.orig/include/infiniband/kern-abi.h ++++ libibverbs-1.1.7/include/infiniband/kern-abi.h +@@ -98,6 +98,13 @@ enum { + #define IB_USER_VERBS_CMD_FLAG_EXTENDED 0x80ul + + ++enum { ++ IB_USER_VERBS_CMD_CREATE_FLOW = (IB_USER_VERBS_CMD_FLAG_EXTENDED << ++ IB_USER_VERBS_CMD_FLAGS_SHIFT) + ++ IB_USER_VERBS_CMD_THRESHOLD, ++ IB_USER_VERBS_CMD_DESTROY_FLOW ++}; ++ + /* + * Make sure that all structs defined in this file remain laid out so + * that they pack the same way on 32-bit and 64-bit architectures (to +@@ -632,6 +639,76 @@ struct ibv_kern_send_wr { + } wr; + }; + ++struct ibv_kern_eth_filter { ++ __u8 dst_mac[6]; ++ __u8 src_mac[6]; ++ __u16 ether_type; ++ __u16 vlan_tag; ++}; ++ ++struct ibv_kern_spec_eth { ++ __u32 type; ++ __u16 size; ++ __u16 reserved; ++ struct ibv_kern_eth_filter val; ++ struct ibv_kern_eth_filter mask; ++}; ++ ++struct ibv_kern_ipv4_filter { ++ __u32 src_ip; ++ __u32 dst_ip; ++}; ++ ++struct ibv_kern_spec_ipv4 { ++ __u32 type; ++ __u16 size; ++ __u16 reserved; ++ struct ibv_kern_ipv4_filter val; ++ struct ibv_kern_ipv4_filter mask; ++}; ++ ++struct ibv_kern_tcp_udp_filter { ++ __u16 dst_port; ++ __u16 src_port; ++}; ++ ++struct ibv_kern_spec_tcp_udp { ++ __u32 type; ++ __u16 size; ++ __u16 reserved; ++ struct ibv_kern_tcp_udp_filter val; ++ struct ibv_kern_tcp_udp_filter mask; ++}; ++ ++ ++struct ibv_kern_spec { ++ union { ++ struct { ++ __u32 type; ++ __u16 size; ++ __u16 reserved; ++ } hdr; ++ struct ibv_kern_spec_eth eth; ++ struct ibv_kern_spec_ipv4 ipv4; ++ struct ibv_kern_spec_tcp_udp tcp_udp; ++ }; ++ ++}; ++ ++struct ibv_kern_flow_attr { ++ __u32 type; ++ __u16 size; ++ __u16 priority; ++ __u8 num_of_specs; ++ __u8 reserved[2]; ++ __u8 port; ++ __u32 flags; ++ /* Following are the optional layers according to user request ++ * struct ibv_kern_flow_spec_xxx ++ * struct ibv_kern_flow_spec_yyy ++ */ ++}; ++ + struct ibv_post_send { + __u32 command; + __u16 in_words; +@@ -719,6 +796,24 @@ struct ibv_attach_mcast { + __u64 driver_data[0]; + }; + ++struct ibv_create_flow { ++ struct ex_hdr hdr; ++ __u32 comp_mask; ++ __u32 qp_handle; ++ struct ibv_kern_flow_attr flow_attr; ++}; ++ ++struct ibv_create_flow_resp { ++ __u32 comp_mask; ++ __u32 flow_handle; ++}; ++ ++struct ibv_destroy_flow { ++ struct ex_hdr hdr; ++ __u32 comp_mask; ++ __u32 flow_handle; ++}; ++ + struct ibv_detach_mcast { + __u32 command; + __u16 in_words; +@@ -840,6 +935,9 @@ enum { + * trick opcodes in IBV_INIT_CMD() doesn't break. + */ + IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1, ++ IB_USER_VERBS_CMD_OPEN_QP_V2 = -1, ++ IB_USER_VERBS_CMD_CREATE_FLOW_V2 = -1, ++ IB_USER_VERBS_CMD_DESTROY_FLOW_V2 = -1 + }; + + struct ibv_modify_srq_v3 { +--- libibverbs-1.1.7.orig/include/infiniband/verbs.h ++++ libibverbs-1.1.7/include/infiniband/verbs.h +@@ -109,7 +109,8 @@ enum ibv_device_cap_flags { + IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11, + IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12, + IBV_DEVICE_SRQ_RESIZE = 1 << 13, +- IBV_DEVICE_N_NOTIFY_CQ = 1 << 14 ++ IBV_DEVICE_N_NOTIFY_CQ = 1 << 14, ++ IBV_DEVICE_MANAGED_FLOW_STEERING = 1 << 29 + }; + + enum ibv_atomic_cap { +@@ -646,6 +647,103 @@ struct ibv_ah { + uint32_t handle; + }; + ++enum ibv_flow_flags { ++ IBV_FLOW_ATTR_FLAGS_ALLOW_LOOP_BACK = 1, ++}; ++ ++enum ibv_flow_attr_type { ++ /* steering according to rule specifications */ ++ IBV_FLOW_ATTR_NORMAL = 0x0, ++ /* default unicast and multicast rule - ++ * receive all Eth traffic which isn't steered to any QP ++ */ ++ IBV_FLOW_ATTR_ALL_DEFAULT = 0x1, ++ /* default multicast rule - ++ * receive all Eth multicast traffic which isn't steered to any QP ++ */ ++ IBV_FLOW_ATTR_MC_DEFAULT = 0x2, ++}; ++ ++enum ibv_flow_spec_type { ++ IBV_FLOW_SPEC_ETH = 0x20, ++ IBV_FLOW_SPEC_IPV4 = 0x30, ++ IBV_FLOW_SPEC_TCP = 0x40, ++ IBV_FLOW_SPEC_UDP = 0x41, ++}; ++ ++struct ibv_flow_eth_filter { ++ uint8_t dst_mac[6]; ++ uint8_t src_mac[6]; ++ uint16_t ether_type; ++ /* ++ * same layout as 802.1q: prio 3, cfi 1, vlan id 12 ++ */ ++ uint16_t vlan_tag; ++}; ++ ++struct ibv_flow_spec_eth { ++ enum ibv_flow_spec_type type; ++ uint16_t size; ++ struct ibv_flow_eth_filter val; ++ struct ibv_flow_eth_filter mask; ++}; ++ ++struct ibv_flow_ipv4_filter { ++ uint32_t src_ip; ++ uint32_t dst_ip; ++}; ++ ++struct ibv_flow_spec_ipv4 { ++ enum ibv_flow_spec_type type; ++ uint16_t size; ++ struct ibv_flow_ipv4_filter val; ++ struct ibv_flow_ipv4_filter mask; ++}; ++ ++struct ibv_flow_tcp_udp_filter { ++ uint16_t dst_port; ++ uint16_t src_port; ++}; ++ ++struct ibv_flow_spec_tcp_udp { ++ enum ibv_flow_spec_type type; ++ uint16_t size; ++ struct ibv_flow_tcp_udp_filter val; ++ struct ibv_flow_tcp_udp_filter mask; ++}; ++ ++struct ibv_flow_spec { ++ union { ++ struct { ++ enum ibv_flow_spec_type type; ++ uint16_t size; ++ } hdr; ++ struct ibv_flow_spec_eth eth; ++ struct ibv_flow_spec_ipv4 ipv4; ++ struct ibv_flow_spec_tcp_udp tcp_udp; ++ }; ++}; ++ ++struct ibv_flow_attr { ++ uint32_t comp_mask; ++ enum ibv_flow_attr_type type; ++ uint16_t size; ++ uint16_t priority; ++ uint8_t num_of_specs; ++ uint8_t port; ++ uint32_t flags; ++ /* Following are the optional layers according to user request ++ * struct ibv_flow_spec_xxx [L2] ++ * struct ibv_flow_spec_yyy [L3/L4] ++ */ ++}; ++ ++struct ibv_flow { ++ uint32_t comp_mask; ++ struct ibv_context *context; ++ uint32_t handle; ++}; ++ + struct ibv_device; + struct ibv_context; + +@@ -753,11 +851,21 @@ struct ibv_context { + }; + + enum verbs_context_mask { +- VERBS_CONTEXT_RESERVED = 1 << 0 ++ VERBS_CONTEXT_CREATE_FLOW = 1 << 0, ++ VERBS_CONTEXT_DESTROY_FLOW = 1 << 1, ++ VERBS_CONTEXT_RESERVED = 1 << 2 + }; + + struct verbs_context { + /* "grows up" - new fields go here */ ++ int (*drv_ibv_destroy_flow) (struct ibv_flow *flow); ++ int (*lib_ibv_destroy_flow) (struct ibv_flow *flow); ++ struct ibv_flow * (*drv_ibv_create_flow) (struct ibv_qp *qp, ++ struct ibv_flow_attr ++ *flow_attr); ++ struct ibv_flow * (*lib_ibv_create_flow) (struct ibv_qp *qp, ++ struct ibv_flow_attr ++ *flow_attr); + uint64_t has_comp_mask; + size_t sz; /* Must be immediately before struct ibv_context */ + struct ibv_context context; /* Must be last field in the struct */ +@@ -907,6 +1015,26 @@ struct ibv_mr *ibv_reg_mr(struct ibv_pd + */ + int ibv_dereg_mr(struct ibv_mr *mr); + ++static inline struct ibv_flow *ibv_create_flow(struct ibv_qp *qp, ++ struct ibv_flow_attr *flow) ++{ ++ struct verbs_context *vctx = verbs_get_ctx_op(qp->context, ++ lib_ibv_create_flow); ++ if (!vctx || !vctx->lib_ibv_create_flow) ++ return NULL; ++ ++ return vctx->lib_ibv_create_flow(qp, flow); ++} ++ ++static inline int ibv_destroy_flow(struct ibv_flow *flow_id) ++{ ++ struct verbs_context *vctx = verbs_get_ctx_op(flow_id->context, ++ lib_ibv_destroy_flow); ++ if (!vctx || !vctx->lib_ibv_destroy_flow) ++ return -ENOSYS; ++ return vctx->lib_ibv_destroy_flow(flow_id); ++} ++ + /** + * ibv_create_comp_channel - Create a completion event channel + */ +--- libibverbs-1.1.7.orig/src/cmd.c ++++ libibverbs-1.1.7/src/cmd.c +@@ -1004,3 +1004,108 @@ int ibv_cmd_detach_mcast(struct ibv_qp * + + return 0; + } ++ ++static int ib_spec_to_kern_spec(struct ibv_flow_spec *ib_spec, ++ struct ibv_kern_spec *kern_spec) ++{ ++ kern_spec->hdr.type = ib_spec->hdr.type; ++ ++ switch (ib_spec->hdr.type) { ++ case IBV_FLOW_SPEC_ETH: ++ kern_spec->eth.size = sizeof(struct ibv_kern_spec_eth); ++ memcpy(&kern_spec->eth.val, &ib_spec->eth.val, ++ sizeof(struct ibv_flow_eth_filter)); ++ memcpy(&kern_spec->eth.mask, &ib_spec->eth.mask, ++ sizeof(struct ibv_flow_eth_filter)); ++ break; ++ case IBV_FLOW_SPEC_IPV4: ++ kern_spec->ipv4.size = sizeof(struct ibv_kern_spec_ipv4); ++ memcpy(&kern_spec->ipv4.val, &ib_spec->ipv4.val, ++ sizeof(struct ibv_flow_ipv4_filter)); ++ memcpy(&kern_spec->ipv4.mask, &ib_spec->ipv4.mask, ++ sizeof(struct ibv_flow_ipv4_filter)); ++ break; ++ case IBV_FLOW_SPEC_TCP: ++ case IBV_FLOW_SPEC_UDP: ++ kern_spec->tcp_udp.size = sizeof(struct ibv_kern_spec_tcp_udp); ++ memcpy(&kern_spec->tcp_udp.val, &ib_spec->tcp_udp.val, ++ sizeof(struct ibv_flow_ipv4_filter)); ++ memcpy(&kern_spec->tcp_udp.mask, &ib_spec->tcp_udp.mask, ++ sizeof(struct ibv_flow_tcp_udp_filter)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++struct ibv_flow *ibv_cmd_create_flow(struct ibv_qp *qp, ++ struct ibv_flow_attr *flow_attr) ++{ ++ struct ibv_create_flow *cmd; ++ struct ibv_create_flow_resp resp; ++ struct ibv_flow *flow_id; ++ size_t cmd_size; ++ size_t written_size; ++ int i, err; ++ void *kern_spec; ++ void *ib_spec; ++ ++ cmd_size = sizeof(*cmd) + (flow_attr->num_of_specs * ++ sizeof(struct ibv_kern_spec)); ++ cmd = alloca(cmd_size); ++ flow_id = malloc(sizeof(*flow_id)); ++ if (!flow_id) ++ return NULL; ++ memset(cmd, 0, cmd_size); ++ ++ cmd->qp_handle = qp->handle; ++ ++ cmd->flow_attr.type = flow_attr->type; ++ cmd->flow_attr.priority = flow_attr->priority; ++ cmd->flow_attr.num_of_specs = flow_attr->num_of_specs; ++ cmd->flow_attr.port = flow_attr->port; ++ cmd->flow_attr.flags = flow_attr->flags; ++ ++ kern_spec = cmd + 1; ++ ib_spec = flow_attr + 1; ++ for (i = 0; i < flow_attr->num_of_specs; i++) { ++ err = ib_spec_to_kern_spec(ib_spec, kern_spec); ++ if (err) ++ goto err; ++ cmd->flow_attr.size += ++ ((struct ibv_kern_spec *)kern_spec)->hdr.size; ++ kern_spec += ((struct ibv_kern_spec *)kern_spec)->hdr.size; ++ ib_spec += ((struct ibv_flow_spec *)ib_spec)->hdr.size; ++ } ++ ++ written_size = sizeof(*cmd) + cmd->flow_attr.size; ++ IBV_INIT_CMD_RESP_EX_VCMD(cmd, written_size, written_size, CREATE_FLOW, ++ &resp, sizeof(resp)); ++ if (write(qp->context->cmd_fd, cmd, written_size) != written_size) ++ goto err; ++ ++ (void) VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof(resp)); ++ ++ flow_id->context = qp->context; ++ flow_id->handle = resp.flow_handle; ++ return flow_id; ++err: ++ free(flow_id); ++ return NULL; ++} ++ ++int ibv_cmd_destroy_flow(struct ibv_flow *flow_id) ++{ ++ struct ibv_destroy_flow cmd; ++ int ret = 0; ++ ++ memset(&cmd, 0, sizeof(cmd)); ++ IBV_INIT_CMD_EX(&cmd, sizeof(cmd), DESTROY_FLOW); ++ cmd.flow_handle = flow_id->handle; ++ ++ if (write(flow_id->context->cmd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) ++ ret = errno; ++ free(flow_id); ++ return ret; ++} +--- libibverbs-1.1.7.orig/src/device.c ++++ libibverbs-1.1.7/src/device.c +@@ -169,6 +169,10 @@ struct ibv_context *__ibv_open_device(st + * context_ex->lib_new_func1 = __verbs_new_func1; + * context_ex->lib_new_func2 = __verbs_new_func2; + */ ++ context_ex->lib_ibv_create_flow = ++ context_ex->drv_ibv_create_flow; ++ context_ex->lib_ibv_destroy_flow = ++ context_ex->drv_ibv_destroy_flow; + } + + context->device = device; +--- libibverbs-1.1.7.orig/src/libibverbs.map ++++ libibverbs-1.1.7/src/libibverbs.map +@@ -64,6 +64,8 @@ IBVERBS_1.0 { + ibv_cmd_destroy_ah; + ibv_cmd_attach_mcast; + ibv_cmd_detach_mcast; ++ ibv_cmd_create_flow; ++ ibv_cmd_destroy_flow; + ibv_copy_qp_attr_from_kern; + ibv_copy_path_rec_from_kern; + ibv_copy_path_rec_to_kern; diff -Nru libibverbs-1.1.7/debian/patches/Infrastructure-to-support-verbs-extensions.patch libibverbs-1.1.7/debian/patches/Infrastructure-to-support-verbs-extensions.patch --- libibverbs-1.1.7/debian/patches/Infrastructure-to-support-verbs-extensions.patch 1969-12-31 21:00:00.000000000 -0300 +++ libibverbs-1.1.7/debian/patches/Infrastructure-to-support-verbs-extensions.patch 2015-08-03 11:42:01.000000000 -0300 @@ -0,0 +1,574 @@ +Description: Infrastructure to support verbs extensions + +Add infrastructure to support extended verbs capabilities in a +forward/backward manner. + +Support for extensions is determined by the provider calling +verbs_register_driver in place of ibv_register_driver. When +extensions are enabled, ibverbs sets the current alloc_context / +free_context device operations to NULL. These are used to indicate +that the struct ibv_device may be cast to struct verbs_device. + +With extensions, ibverbs allocates the ibv_context structure and calls +into the provider to initialize it. The init call is part of the +verbs_device struct. + +The abi_compat field of struct ibv_context is used to determine +support of verbs extensions. As a result, support for ABI version < 2 +is removed (corresponds to kernel releases 2.6.11-2.6.14 no longer +being supported). The lowest ABI now supported is 3 (really 4 since + 2.6.15 was ABI 4, I don't see that ABI 3 was in a release). + +Author: Yishai Hadas +Acked-by: Jason Gunthorpe +Signed-off-by: Yishai Hadas +Signed-off-by: Tzahi Oved +Signed-off-by: Sean Hefty +Signed-off-by: Roland Dreier + +Origin: upstream, commit: 6be16586e081728a28fc41ce2fcc41867b7375ec +Bug-Ubuntu: https://launchpad.net/bugs/1409904 +Last-Update: 2015-02-09 + +--- libibverbs-1.1.7.orig/include/infiniband/driver.h ++++ libibverbs-1.1.7/include/infiniband/driver.h +@@ -55,8 +55,11 @@ + + typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path, + int abi_version); ++typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path, ++ int abi_version); + + void ibv_register_driver(const char *name, ibv_driver_init_func init_func); ++void verbs_register_driver(const char *name, verbs_driver_init_func init_func); + int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd, + size_t cmd_size, struct ibv_get_context_resp *resp, + size_t resp_size); +--- libibverbs-1.1.7.orig/include/infiniband/kern-abi.h ++++ libibverbs-1.1.7/include/infiniband/kern-abi.h +@@ -45,7 +45,7 @@ + /* + * The minimum and maximum kernel ABI that we can handle. + */ +-#define IB_USER_VERBS_MIN_ABI_VERSION 1 ++#define IB_USER_VERBS_MIN_ABI_VERSION 3 + #define IB_USER_VERBS_MAX_ABI_VERSION 6 + + enum { +@@ -806,47 +806,6 @@ enum { + IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1, + }; + +-struct ibv_destroy_cq_v1 { +- __u32 command; +- __u16 in_words; +- __u16 out_words; +- __u32 cq_handle; +-}; +- +-struct ibv_destroy_qp_v1 { +- __u32 command; +- __u16 in_words; +- __u16 out_words; +- __u32 qp_handle; +-}; +- +-struct ibv_destroy_srq_v1 { +- __u32 command; +- __u16 in_words; +- __u16 out_words; +- __u32 srq_handle; +-}; +- +-struct ibv_get_context_v2 { +- __u32 command; +- __u16 in_words; +- __u16 out_words; +- __u64 response; +- __u64 cq_fd_tab; +- __u64 driver_data[0]; +-}; +- +-struct ibv_create_cq_v2 { +- __u32 command; +- __u16 in_words; +- __u16 out_words; +- __u64 response; +- __u64 user_handle; +- __u32 cqe; +- __u32 event_handler; +- __u64 driver_data[0]; +-}; +- + struct ibv_modify_srq_v3 { + __u32 command; + __u16 in_words; +--- libibverbs-1.1.7.orig/include/infiniband/verbs.h ++++ libibverbs-1.1.7/include/infiniband/verbs.h +@@ -38,6 +38,8 @@ + + #include + #include ++#include ++#include + + #ifdef __cplusplus + # define BEGIN_C_DECLS extern "C" { +@@ -63,6 +65,22 @@ union ibv_gid { + } global; + }; + ++#ifndef container_of ++/** ++ * container_of - cast a member of a structure out to the containing structure ++ * @ptr: the pointer to the member. ++ * @type: the type of the container struct this is embedded in. ++ * @member: the name of the member within the struct. ++ * ++ */ ++#define container_of(ptr, type, member) \ ++ ((type *) ((uint8_t *)(ptr) - offsetof(type, member))) ++#endif ++ ++#define vext_field_avail(type, fld, sz) (offsetof(type, fld) < (sz)) ++ ++static void *__VERBS_ABI_IS_EXTENDED = ((uint8_t *) NULL) - 1; ++ + enum ibv_node_type { + IBV_NODE_UNKNOWN = -1, + IBV_NODE_CA = 1, +@@ -656,6 +674,17 @@ struct ibv_device { + char ibdev_path[IBV_SYSFS_PATH_MAX]; + }; + ++struct verbs_device { ++ struct ibv_device device; /* Must be first */ ++ size_t sz; ++ size_t size_of_context; ++ int (*init_context)(struct verbs_device *device, ++ struct ibv_context *ctx, int cmd_fd); ++ void (*uninit_context)(struct verbs_device *device, ++ struct ibv_context *ctx); ++ /* future fields added here */ ++}; ++ + struct ibv_context_ops { + int (*query_device)(struct ibv_context *context, + struct ibv_device_attr *device_attr); +@@ -724,6 +753,40 @@ struct ibv_context { + void *abi_compat; + }; + ++enum verbs_context_mask { ++ VERBS_CONTEXT_RESERVED = 1 << 0 ++}; ++ ++struct verbs_context { ++ /* "grows up" - new fields go here */ ++ uint64_t has_comp_mask; ++ size_t sz; /* Must be immediately before struct ibv_context */ ++ struct ibv_context context; /* Must be last field in the struct */ ++}; ++ ++static inline struct verbs_context *verbs_get_ctx(struct ibv_context *ctx) ++{ ++ return (ctx->abi_compat != __VERBS_ABI_IS_EXTENDED) ? ++ NULL : container_of(ctx, struct verbs_context, context); ++} ++ ++#define verbs_get_ctx_op(ctx, op) ({ \ ++ struct verbs_context *vctx = verbs_get_ctx(ctx); \ ++ (!vctx || (vctx->sz < sizeof(*vctx) - offsetof(struct verbs_context, op)) || \ ++ !vctx->op) ? NULL : vctx; }) ++ ++#define verbs_set_ctx_op(_vctx, op, ptr) ({ \ ++ struct verbs_context *vctx = _vctx; \ ++ if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \ ++ vctx->op = ptr; }) ++ ++static inline struct verbs_device *verbs_get_device( ++ const struct ibv_device *dev) ++{ ++ return (dev->ops.alloc_context) ? ++ NULL : container_of(dev, struct verbs_device, device); ++} ++ + /** + * ibv_get_device_list - Get list of IB devices currently available + * @num_devices: optional. if non-NULL, set to the number of devices +--- libibverbs-1.1.7.orig/src/cmd.c ++++ libibverbs-1.1.7/src/cmd.c +@@ -45,52 +45,13 @@ + + #include "ibverbs.h" + +-static int ibv_cmd_get_context_v2(struct ibv_context *context, +- struct ibv_get_context *new_cmd, +- size_t new_cmd_size, +- struct ibv_get_context_resp *resp, +- size_t resp_size) +-{ +- struct ibv_abi_compat_v2 *t; +- struct ibv_get_context_v2 *cmd; +- size_t cmd_size; +- uint32_t cq_fd; +- +- t = malloc(sizeof *t); +- if (!t) +- return ENOMEM; +- pthread_mutex_init(&t->in_use, NULL); +- +- cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd; +- cmd = alloca(cmd_size); +- memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd); +- +- IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size); +- cmd->cq_fd_tab = (uintptr_t) &cq_fd; +- +- if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) { +- free(t); +- return errno; +- } +- +- (void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size); +- +- context->async_fd = resp->async_fd; +- context->num_comp_vectors = 1; +- t->channel.context = context; +- t->channel.fd = cq_fd; +- t->channel.refcnt = 0; +- context->abi_compat = t; +- +- return 0; +-} + + int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd, + size_t cmd_size, struct ibv_get_context_resp *resp, + size_t resp_size) + { +- if (abi_ver <= 2) +- return ibv_cmd_get_context_v2(context, cmd, cmd_size, resp, resp_size); ++ if (abi_ver < IB_USER_VERBS_MIN_ABI_VERSION) ++ return ENOSYS; + + IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size); + +@@ -274,45 +235,12 @@ int ibv_cmd_dereg_mr(struct ibv_mr *mr) + return 0; + } + +-static int ibv_cmd_create_cq_v2(struct ibv_context *context, int cqe, +- struct ibv_cq *cq, +- struct ibv_create_cq *new_cmd, size_t new_cmd_size, +- struct ibv_create_cq_resp *resp, size_t resp_size) +-{ +- struct ibv_create_cq_v2 *cmd; +- size_t cmd_size; +- +- cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd; +- cmd = alloca(cmd_size); +- memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd); +- +- IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size); +- cmd->user_handle = (uintptr_t) cq; +- cmd->cqe = cqe; +- cmd->event_handler = 0; +- +- if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) +- return errno; +- +- (void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size); +- +- cq->handle = resp->cq_handle; +- cq->cqe = resp->cqe; +- cq->context = context; +- +- return 0; +-} +- + int ibv_cmd_create_cq(struct ibv_context *context, int cqe, + struct ibv_comp_channel *channel, + int comp_vector, struct ibv_cq *cq, + struct ibv_create_cq *cmd, size_t cmd_size, + struct ibv_create_cq_resp *resp, size_t resp_size) + { +- if (abi_ver <= 2) +- return ibv_cmd_create_cq_v2(context, cqe, cq, +- cmd, cmd_size, resp, resp_size); +- + IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size); + cmd->user_handle = (uintptr_t) cq; + cmd->cqe = cqe; +@@ -397,7 +325,6 @@ int ibv_cmd_resize_cq(struct ibv_cq *cq, + struct ibv_resize_cq *cmd, size_t cmd_size, + struct ibv_resize_cq_resp *resp, size_t resp_size) + { +- + IBV_INIT_CMD_RESP(cmd, cmd_size, RESIZE_CQ, resp, resp_size); + cmd->cq_handle = cq->handle; + cmd->cqe = cqe; +@@ -412,27 +339,11 @@ int ibv_cmd_resize_cq(struct ibv_cq *cq, + return 0; + } + +-static int ibv_cmd_destroy_cq_v1(struct ibv_cq *cq) +-{ +- struct ibv_destroy_cq_v1 cmd; +- +- IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_CQ); +- cmd.cq_handle = cq->handle; +- +- if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) +- return errno; +- +- return 0; +-} +- + int ibv_cmd_destroy_cq(struct ibv_cq *cq) + { + struct ibv_destroy_cq cmd; + struct ibv_destroy_cq_resp resp; + +- if (abi_ver == 1) +- return ibv_cmd_destroy_cq_v1(cq); +- + IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_CQ, &resp, sizeof resp); + cmd.cq_handle = cq->handle; + cmd.reserved = 0; +@@ -557,27 +468,11 @@ int ibv_cmd_query_srq(struct ibv_srq *sr + return 0; + } + +-static int ibv_cmd_destroy_srq_v1(struct ibv_srq *srq) +-{ +- struct ibv_destroy_srq_v1 cmd; +- +- IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_SRQ); +- cmd.srq_handle = srq->handle; +- +- if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) +- return errno; +- +- return 0; +-} +- + int ibv_cmd_destroy_srq(struct ibv_srq *srq) + { + struct ibv_destroy_srq cmd; + struct ibv_destroy_srq_resp resp; + +- if (abi_ver == 1) +- return ibv_cmd_destroy_srq_v1(srq); +- + IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_SRQ, &resp, sizeof resp); + cmd.srq_handle = srq->handle; + cmd.reserved = 0; +@@ -799,19 +694,6 @@ int ibv_cmd_modify_qp(struct ibv_qp *qp, + return 0; + } + +-static int ibv_cmd_destroy_qp_v1(struct ibv_qp *qp) +-{ +- struct ibv_destroy_qp_v1 cmd; +- +- IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_QP); +- cmd.qp_handle = qp->handle; +- +- if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) +- return errno; +- +- return 0; +-} +- + int ibv_cmd_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr, + struct ibv_send_wr **bad_wr) + { +@@ -1074,9 +956,6 @@ int ibv_cmd_destroy_qp(struct ibv_qp *qp + struct ibv_destroy_qp cmd; + struct ibv_destroy_qp_resp resp; + +- if (abi_ver == 1) +- return ibv_cmd_destroy_qp_v1(qp); +- + IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_QP, &resp, sizeof resp); + cmd.qp_handle = qp->handle; + cmd.reserved = 0; +--- libibverbs-1.1.7.orig/src/device.c ++++ libibverbs-1.1.7/src/device.c +@@ -124,9 +124,11 @@ default_symver(__ibv_get_device_guid, ib + + struct ibv_context *__ibv_open_device(struct ibv_device *device) + { ++ struct verbs_device *verbs_device = verbs_get_device(device); + char *devpath; +- int cmd_fd; ++ int cmd_fd, ret; + struct ibv_context *context; ++ struct verbs_context *context_ex; + + if (asprintf(&devpath, "/dev/infiniband/%s", device->dev_name) < 0) + return NULL; +@@ -141,9 +143,33 @@ struct ibv_context *__ibv_open_device(st + if (cmd_fd < 0) + return NULL; + +- context = device->ops.alloc_context(device, cmd_fd); +- if (!context) +- goto err; ++ if (!verbs_device) { ++ context = device->ops.alloc_context(device, cmd_fd); ++ if (!context) ++ goto err; ++ } else { ++ /* Library now allocates the context */ ++ context_ex = calloc(1, sizeof(*context_ex) + ++ verbs_device->size_of_context); ++ if (!context_ex) { ++ errno = ENOMEM; ++ goto err; ++ } ++ ++ context_ex->context.abi_compat = __VERBS_ABI_IS_EXTENDED; ++ context_ex->sz = sizeof(*context_ex); ++ ++ context = &context_ex->context; ++ ret = verbs_device->init_context(verbs_device, context, cmd_fd); ++ if (ret) ++ goto verbs_err; ++ ++ /* initialize *all* library ops to either lib calls or ++ * directly to provider calls. ++ * context_ex->lib_new_func1 = __verbs_new_func1; ++ * context_ex->lib_new_func2 = __verbs_new_func2; ++ */ ++ } + + context->device = device; + context->cmd_fd = cmd_fd; +@@ -151,9 +177,10 @@ struct ibv_context *__ibv_open_device(st + + return context; + ++verbs_err: ++ free(context_ex); + err: + close(cmd_fd); +- + return NULL; + } + default_symver(__ibv_open_device, ibv_open_device); +@@ -163,15 +190,17 @@ int __ibv_close_device(struct ibv_contex + int async_fd = context->async_fd; + int cmd_fd = context->cmd_fd; + int cq_fd = -1; ++ struct verbs_context *context_ex; + +- if (abi_ver <= 2) { +- struct ibv_abi_compat_v2 *t = context->abi_compat; +- cq_fd = t->channel.fd; +- free(context->abi_compat); ++ context_ex = verbs_get_ctx(context); ++ if (context_ex) { ++ struct verbs_device *verbs_device = verbs_get_device(context->device); ++ verbs_device->uninit_context(verbs_device, context); ++ free(context_ex); ++ } else { ++ context->device->ops.free_context(context); + } + +- context->device->ops.free_context(context); +- + close(async_fd); + close(cmd_fd); + if (abi_ver <= 2) +--- libibverbs-1.1.7.orig/src/init.c ++++ libibverbs-1.1.7/src/init.c +@@ -70,6 +70,7 @@ struct ibv_driver_name { + struct ibv_driver { + const char *name; + ibv_driver_init_func init_func; ++ verbs_driver_init_func verbs_init_func; + struct ibv_driver *next; + }; + +@@ -153,7 +154,8 @@ static int find_sysfs_devs(void) + return ret; + } + +-void ibv_register_driver(const char *name, ibv_driver_init_func init_func) ++static void register_driver(const char *name, ibv_driver_init_func init_func, ++ verbs_driver_init_func verbs_init_func) + { + struct ibv_driver *driver; + +@@ -163,9 +165,10 @@ void ibv_register_driver(const char *nam + return; + } + +- driver->name = name; +- driver->init_func = init_func; +- driver->next = NULL; ++ driver->name = name; ++ driver->init_func = init_func; ++ driver->verbs_init_func = verbs_init_func; ++ driver->next = NULL; + + if (tail_driver) + tail_driver->next = driver; +@@ -174,6 +177,19 @@ void ibv_register_driver(const char *nam + tail_driver = driver; + } + ++void ibv_register_driver(const char *name, ibv_driver_init_func init_func) ++{ ++ register_driver(name, init_func, NULL); ++} ++ ++/* New registration symbol with same functionality - used by providers to ++ * validate that library supports verbs extension. ++ */ ++void verbs_register_driver(const char *name, verbs_driver_init_func init_func) ++{ ++ register_driver(name, NULL, init_func); ++} ++ + static void load_driver(const char *name) + { + char *so_name; +@@ -333,12 +349,23 @@ out: + static struct ibv_device *try_driver(struct ibv_driver *driver, + struct ibv_sysfs_dev *sysfs_dev) + { ++ struct verbs_device *vdev; + struct ibv_device *dev; + char value[8]; + +- dev = driver->init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver); +- if (!dev) +- return NULL; ++ if (driver->init_func) { ++ dev = driver->init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver); ++ if (!dev) ++ return NULL; ++ } else { ++ vdev = driver->verbs_init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver); ++ if (!vdev) ++ return NULL; ++ ++ dev = &vdev->device; ++ dev->ops.alloc_context = NULL; ++ dev->ops.free_context = NULL; ++ } + + if (ibv_read_sysfs_file(sysfs_dev->ibdev_path, "node_type", value, sizeof value) < 0) { + fprintf(stderr, PFX "Warning: no node_type attr under %s.\n", +--- libibverbs-1.1.7.orig/src/libibverbs.map ++++ libibverbs-1.1.7/src/libibverbs.map +@@ -91,6 +91,7 @@ IBVERBS_1.1 { + ibv_dontfork_range; + ibv_dofork_range; + ibv_register_driver; ++ verbs_register_driver; + + ibv_node_type_str; + ibv_port_state_str; diff -Nru libibverbs-1.1.7/debian/patches/series libibverbs-1.1.7/debian/patches/series --- libibverbs-1.1.7/debian/patches/series 1969-12-31 21:00:00.000000000 -0300 +++ libibverbs-1.1.7/debian/patches/series 2015-08-03 11:42:01.000000000 -0300 @@ -0,0 +1,4 @@ +Infrastructure-to-support-verbs-extensions.patch +Add-general-definitions-to-support-uverbs-extensions.patch +Add-receive-flow-steering-support.patch +Add-checksum-offload-support-capability.patch