diff --git a/libibverbs/CMakeLists.txt b/libibverbs/CMakeLists.txt
index 4a5832c..6e20c23 100644
--- a/libibverbs/CMakeLists.txt
+++ b/libibverbs/CMakeLists.txt
@@ -29,6 +29,7 @@ rdma_library(ibverbs "${CMAKE_CURRENT_BINARY_DIR}/libibverbs.map"
   # See Documentation/versioning.md
   1 1.1.${PACKAGE_VERSION}
   cmd.c
+  cmd_counters.c
   cmd_cq.c
   cmd_dm.c
   cmd_fallback.c
diff --git a/libibverbs/cmd_counters.c b/libibverbs/cmd_counters.c
new file mode 100644
index 0000000..03e8a8e
--- /dev/null
+++ b/libibverbs/cmd_counters.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018 Mellanox Technologies, Ltd.  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 <infiniband/cmd_ioctl.h>
+#include <rdma/ib_user_ioctl_cmds.h>
+#include <infiniband/driver.h>
+
+int ibv_cmd_create_counters(struct ibv_context *context,
+			    struct ibv_counters_init_attr *init_attr,
+			    struct verbs_counters *vcounters,
+			    struct ibv_command_buffer *link)
+{
+	DECLARE_COMMAND_BUFFER_LINK(cmd, UVERBS_OBJECT_COUNTERS,
+				    UVERBS_METHOD_COUNTERS_CREATE,
+				    1,
+				    link);
+	struct ib_uverbs_attr *handle =
+		fill_attr_out_obj(cmd, UVERBS_ATTR_CREATE_COUNTERS_HANDLE);
+	int ret;
+
+	if (!check_comp_mask(init_attr->comp_mask, 0))
+		return EOPNOTSUPP;
+
+	ret = execute_ioctl(context, cmd);
+	if (ret)
+		return ret;
+
+	vcounters->counters.context = context;
+	vcounters->handle = read_attr_obj(UVERBS_ATTR_CREATE_COUNTERS_HANDLE, handle);
+
+	return 0;
+}
+
+int ibv_cmd_destroy_counters(struct verbs_counters *vcounters)
+{
+	DECLARE_COMMAND_BUFFER(cmd, UVERBS_OBJECT_COUNTERS,
+			       UVERBS_METHOD_COUNTERS_DESTROY,
+			       1);
+
+	fill_attr_in_obj(cmd, UVERBS_ATTR_DESTROY_COUNTERS_HANDLE, vcounters->handle);
+	return execute_ioctl(vcounters->counters.context, cmd);
+}
diff --git a/libibverbs/driver.h b/libibverbs/driver.h
index ca61827..11a6d08 100644
--- a/libibverbs/driver.h
+++ b/libibverbs/driver.h
@@ -188,6 +188,11 @@ struct verbs_device {
 	struct verbs_sysfs_dev *sysfs;
 };
 
+struct verbs_counters {
+	struct ibv_counters counters;
+	uint32_t handle;
+};
+
 /*
  * Must change the PRIVATE IBVERBS_PRIVATE_ symbol if this is changed. This is
  * the union of every op the driver can support. If new elements are added to
@@ -214,6 +219,8 @@ struct verbs_context_ops {
 	void (*cq_event)(struct ibv_cq *cq);
 	struct ibv_ah *(*create_ah)(struct ibv_pd *pd,
 				    struct ibv_ah_attr *attr);
+	struct ibv_counters *(*create_counters)(struct ibv_context *context,
+						struct ibv_counters_init_attr *init_attr);
 	struct ibv_cq *(*create_cq)(struct ibv_context *context, int cqe,
 				    struct ibv_comp_channel *channel,
 				    int comp_vector);
@@ -244,6 +251,7 @@ struct verbs_context_ops {
 	int (*dealloc_td)(struct ibv_td *td);
 	int (*dereg_mr)(struct ibv_mr *mr);
 	int (*destroy_ah)(struct ibv_ah *ah);
+	int (*destroy_counters)(struct ibv_counters *counters);
 	int (*destroy_cq)(struct ibv_cq *cq);
 	int (*destroy_flow)(struct ibv_flow *flow);
 	int (*destroy_flow_action)(struct ibv_flow_action *action);
@@ -526,6 +534,11 @@ int ibv_cmd_create_rwq_ind_table(struct ibv_context *context,
 				 size_t resp_core_size,
 				 size_t resp_size);
 int ibv_cmd_destroy_rwq_ind_table(struct ibv_rwq_ind_table *rwq_ind_table);
+int ibv_cmd_create_counters(struct ibv_context *context,
+			    struct ibv_counters_init_attr *init_attr,
+			    struct verbs_counters *vcounters,
+			    struct ibv_command_buffer *link);
+int ibv_cmd_destroy_counters(struct verbs_counters *vcounters);
 int ibv_dontfork_range(void *base, size_t size);
 int ibv_dofork_range(void *base, size_t size);
 int ibv_cmd_alloc_dm(struct ibv_context *ctx,
diff --git a/libibverbs/dummy_ops.c b/libibverbs/dummy_ops.c
index 2b8b18f..3f4d641 100644
--- a/libibverbs/dummy_ops.c
+++ b/libibverbs/dummy_ops.c
@@ -98,6 +98,13 @@ static struct ibv_ah *create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr)
 	return NULL;
 }
 
+static struct ibv_counters *create_counters(struct ibv_context *context,
+					    struct ibv_counters_init_attr *init_attr)
+{
+	errno = ENOSYS;
+	return NULL;
+}
+
 static struct ibv_cq *create_cq(struct ibv_context *context, int cqe,
 				struct ibv_comp_channel *channel,
 				int comp_vector)
@@ -196,6 +203,11 @@ static int destroy_ah(struct ibv_ah *ah)
 	return ENOSYS;
 }
 
+static int destroy_counters(struct ibv_counters *counters)
+{
+	return ENOSYS;
+}
+
 static int destroy_cq(struct ibv_cq *cq)
 {
 	return ENOSYS;
@@ -414,6 +426,7 @@ const struct verbs_context_ops verbs_dummy_ops = {
 	close_xrcd,
 	cq_event,
 	create_ah,
+	create_counters,
 	create_cq,
 	create_cq_ex,
 	create_flow,
@@ -429,6 +442,7 @@ const struct verbs_context_ops verbs_dummy_ops = {
 	dealloc_td,
 	dereg_mr,
 	destroy_ah,
+	destroy_counters,
 	destroy_cq,
 	destroy_flow,
 	destroy_flow_action,
@@ -498,6 +512,7 @@ void verbs_set_ops(struct verbs_context *vctx,
 	SET_OP(vctx, close_xrcd);
 	SET_OP(ctx, cq_event);
 	SET_OP(ctx, create_ah);
+	SET_OP(vctx, create_counters);
 	SET_OP(ctx, create_cq);
 	SET_OP(vctx, create_cq_ex);
 	SET_OP2(vctx, ibv_create_flow, create_flow);
@@ -513,6 +528,7 @@ void verbs_set_ops(struct verbs_context *vctx,
 	SET_OP(vctx, dealloc_td);
 	SET_OP(ctx, dereg_mr);
 	SET_OP(ctx, destroy_ah);
+	SET_OP(vctx, destroy_counters);
 	SET_OP(ctx, destroy_cq);
 	SET_OP2(vctx, ibv_destroy_flow, destroy_flow);
 	SET_OP(vctx, destroy_flow_action);
diff --git a/libibverbs/libibverbs.map.in b/libibverbs/libibverbs.map.in
index 7322fe3..d66a8d3 100644
--- a/libibverbs/libibverbs.map.in
+++ b/libibverbs/libibverbs.map.in
@@ -121,6 +121,7 @@ IBVERBS_PRIVATE_@IBVERBS_PABI_VERSION@ {
 		ibv_cmd_attach_mcast;
 		ibv_cmd_close_xrcd;
 		ibv_cmd_create_ah;
+		ibv_cmd_create_counters;
 		ibv_cmd_create_cq;
 		ibv_cmd_create_cq_ex;
 		ibv_cmd_create_flow;
@@ -136,6 +137,7 @@ IBVERBS_PRIVATE_@IBVERBS_PABI_VERSION@ {
 		ibv_cmd_dealloc_pd;
 		ibv_cmd_dereg_mr;
 		ibv_cmd_destroy_ah;
+		ibv_cmd_destroy_counters;
 		ibv_cmd_destroy_cq;
 		ibv_cmd_destroy_flow;
 		ibv_cmd_destroy_flow_action;
diff --git a/libibverbs/man/CMakeLists.txt b/libibverbs/man/CMakeLists.txt
index 86dd49d..aa5a07a 100644
--- a/libibverbs/man/CMakeLists.txt
+++ b/libibverbs/man/CMakeLists.txt
@@ -10,6 +10,7 @@ rdma_man_pages(
   ibv_create_ah.3
   ibv_create_ah_from_wc.3
   ibv_create_comp_channel.3
+  ibv_create_counters.3.md
   ibv_create_cq.3
   ibv_create_cq_ex.3
   ibv_modify_cq.3
@@ -76,6 +77,7 @@ rdma_alias_man_pages(
   ibv_create_ah.3 ibv_destroy_ah.3
   ibv_create_ah_from_wc.3 ibv_init_ah_from_wc.3
   ibv_create_comp_channel.3 ibv_destroy_comp_channel.3
+  ibv_create_counters.3 ibv_destroy_counters.3
   ibv_create_cq.3 ibv_destroy_cq.3
   ibv_create_flow.3 ibv_destroy_flow.3
   ibv_create_flow_action.3 ibv_destroy_flow_action.3
diff --git a/libibverbs/man/ibv_create_counters.3.md b/libibverbs/man/ibv_create_counters.3.md
new file mode 100644
index 0000000..d7f062a
--- /dev/null
+++ b/libibverbs/man/ibv_create_counters.3.md
@@ -0,0 +1,97 @@
+---
+date: 2018-04-02
+footer: libibverbs
+header: "Libibverbs Programmer's Manual"
+layout: page
+license: 'Licensed under the OpenIB.org BSD license (FreeBSD Variant) - See COPYING.md'
+section: 3
+title: IBV_CREATE_COUNTERS
+tagline: Verbs
+---
+
+# NAME
+
+**ibv_create_counters**(3), **ibv_destroy_counters**(3) -- Create or destroy a counters handle
+
+# SYNOPSIS
+
+```c
+#include <infiniband/verbs.h>
+
+struct ibv_counters *
+ibv_create_counters(struct ibv_context *context,
+                    struct ibv_counters_init_attr *init_attr);
+
+int ibv_destroy_counters(struct ibv_counters *counters);
+```
+
+# DESCRIPTION
+
+**ibv_create_counters**() creates a new counters handle for the RDMA device
+context.
+
+An ibv_counters handle can be attached to a verbs resource (e.g.: QP, WQ, Flow)
+statically when these are created.
+
+For example attach an ibv_counters statically to a Flow (struct ibv_flow) during
+creation of a new Flow by calling **ibv_create_flow()**.
+
+Counters are cleared upon creation and values will be monotonically increasing.
+
+**ibv_destroy_counters**() releases the counters handle, user should
+detach the counters object before destroying it.
+
+# ARGUMENTS
+
+*context*
+:	RDMA device context to create the counters on.
+
+*init_attr*
+:	Is an ibv_counters_init_attr struct, as defined in verbs.h.
+
+## *init_attr* Argument
+
+```c
+struct ibv_counters_init_attr {
+	int comp_mask;
+};
+```
+
+*comp_mask*
+:	Bitmask specifying what fields in the structure are valid.
+
+# RETURN VALUE
+
+**ibv_create_counters**() returns a pointer to the allocated ibv_counters
+object, or NULL if the request fails (and sets errno to indicate the failure
+reason)
+
+**ibv_destroy_counters**() returns 0 on success, or the value of errno on
+failure (which indicates the failure reason)
+
+# ERRORS
+
+ENOSYS
+:	**ibv_create_counters**() is not currently supported on this device
+
+ENOMEM
+:	**ibv_create_counters**() could not create ibv_counters object, not enough memory
+
+EINVAL
+:	invalid parameter supplied **ibv_destroy_counters**()
+
+# EXAMPLE
+
+An example of use of ibv_counters is shown in **ibv_read_counters**(3)
+
+# SEE ALSO
+
+**ibv_attach_counters_point_flow**(3), **ibv_read_counters**(3),
+**ibv_create_flow**(3)
+
+# AUTHORS
+
+Raed Salem <raeds@mellanox.com>
+
+Alex Rosenbaum <alexr@mellanox.com>
+
diff --git a/libibverbs/verbs.h b/libibverbs/verbs.h
index eb57824..6eceadc 100644
--- a/libibverbs/verbs.h
+++ b/libibverbs/verbs.h
@@ -1718,6 +1718,14 @@ struct ibv_parent_domain_init_attr {
 	uint32_t comp_mask;
 };
 
+struct ibv_counters_init_attr {
+	uint32_t	comp_mask;
+};
+
+struct ibv_counters {
+	struct ibv_context	*context;
+};
+
 enum ibv_values_mask {
 	IBV_VALUES_MASK_RAW_CLOCK	= 1 << 0,
 	IBV_VALUES_MASK_RESERVED	= 1 << 1
@@ -1730,6 +1738,9 @@ struct ibv_values_ex {
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	struct ibv_counters *(*create_counters)(struct ibv_context *context,
+						struct ibv_counters_init_attr *init_attr);
+	int (*destroy_counters)(struct ibv_counters *counters);
 	struct ibv_mr *(*reg_dm_mr)(struct ibv_pd *pd, struct ibv_dm *dm,
 				    uint64_t dm_offset, size_t length,
 				    unsigned int access);
@@ -2797,6 +2808,31 @@ static inline int ibv_is_qpt_supported(uint32_t caps, enum ibv_qp_type qpt)
 	return !!(caps & (1 << qpt));
 }
 
+static inline struct ibv_counters *ibv_create_counters(struct ibv_context *context,
+						       struct ibv_counters_init_attr *init_attr)
+{
+	struct verbs_context *vctx;
+
+	vctx = verbs_get_ctx_op(context, create_counters);
+	if (!vctx) {
+		errno = ENOSYS;
+		return NULL;
+	}
+
+	return vctx->create_counters(context, init_attr);
+}
+
+static inline int ibv_destroy_counters(struct ibv_counters *counters)
+{
+	struct verbs_context *vctx;
+
+	vctx = verbs_get_ctx_op(counters->context, destroy_counters);
+	if (!vctx)
+		return ENOSYS;
+
+	return vctx->destroy_counters(counters);
+}
+
 #ifdef __cplusplus
 }
 #endif
