diff --git a/libibverbs/driver.h b/libibverbs/driver.h
index 11a6d08..1030b0c 100644
--- a/libibverbs/driver.h
+++ b/libibverbs/driver.h
@@ -211,6 +211,9 @@ struct verbs_context_ops {
 	struct ibv_td *(*alloc_td)(struct ibv_context *context,
 				   struct ibv_td_init_attr *init_attr);
 	void (*async_event)(struct ibv_async_event *event);
+	int (*attach_counters_point_flow)(struct ibv_counters *counters,
+					  struct ibv_counter_attach_attr *attr,
+					  struct ibv_flow *flow);
 	int (*attach_mcast)(struct ibv_qp *qp, const union ibv_gid *gid,
 			    uint16_t lid);
 	int (*bind_mw)(struct ibv_qp *qp, struct ibv_mw *mw,
diff --git a/libibverbs/dummy_ops.c b/libibverbs/dummy_ops.c
index 3f4d641..1ccb5b3 100644
--- a/libibverbs/dummy_ops.c
+++ b/libibverbs/dummy_ops.c
@@ -71,6 +71,13 @@ static void async_event(struct ibv_async_event *event)
 {
 }
 
+static int attach_counters_point_flow(struct ibv_counters *counters,
+				      struct ibv_counter_attach_attr *attr,
+				      struct ibv_flow *flow)
+{
+	return ENOSYS;
+}
+
 static int attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid,
 			uint16_t lid)
 {
@@ -421,6 +428,7 @@ const struct verbs_context_ops verbs_dummy_ops = {
 	alloc_pd,
 	alloc_td,
 	async_event,
+	attach_counters_point_flow,
 	attach_mcast,
 	bind_mw,
 	close_xrcd,
@@ -507,6 +515,7 @@ void verbs_set_ops(struct verbs_context *vctx,
 	SET_OP(vctx, alloc_parent_domain);
 	SET_OP(vctx, alloc_td);
 	SET_OP(ctx, async_event);
+	SET_OP(vctx, attach_counters_point_flow);
 	SET_OP(ctx, attach_mcast);
 	SET_OP(ctx, bind_mw);
 	SET_OP(vctx, close_xrcd);
diff --git a/libibverbs/man/CMakeLists.txt b/libibverbs/man/CMakeLists.txt
index aa5a07a..c4fec80 100644
--- a/libibverbs/man/CMakeLists.txt
+++ b/libibverbs/man/CMakeLists.txt
@@ -5,6 +5,7 @@ rdma_man_pages(
   ibv_alloc_pd.3
   ibv_alloc_td.3
   ibv_asyncwatch.1
+  ibv_attach_counters_point_flow.3.md
   ibv_attach_mcast.3.md
   ibv_bind_mw.3
   ibv_create_ah.3
diff --git a/libibverbs/man/ibv_attach_counters_point_flow.3.md b/libibverbs/man/ibv_attach_counters_point_flow.3.md
new file mode 100644
index 0000000..8aee43e
--- /dev/null
+++ b/libibverbs/man/ibv_attach_counters_point_flow.3.md
@@ -0,0 +1,134 @@
+---
+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_ATTACH_COUNTERS_POINT
+---
+# NAME
+
+**ibv_attach_counters_point_flow**(3) - attach individual counter definition to
+a flow object
+
+# SYNOPSIS
+
+```c
+#include <infiniband/verbs.h>
+
+int ibv_attach_counters_point_flow(struct ibv_counters *counters,
+                                   struct ibv_counter_attach_attr *counter_attach_attr,
+                                   struct ibv_flow *flow);
+```
+
+# DESCRIPTION
+
+Attach counters point are a family of APIs to attach individual counter
+description definition to a verb object at a specific index location.
+
+Counters object will start collecting values after it is bound to the verb object
+resource.
+
+A static attach can be created when NULL is provided instead of the reference
+to the verbs object (e.g.: in case of flow providing NULL instead of *flow*).
+In this case, this counters object will only start collecting values after it is
+bound to the verbs resource, for flow this is when referencing the counters handle
+when creating a flow with **ibv_create_flow**().
+
+Once an ibv_counters is bound statically to a verbs resource, no additional attach
+is allowed till the counter object is not bound to any verb object.
+
+The argument counter_desc specifies which counter value should be collected. It
+is defined in verbs.h as one of the enum ibv_counter_description options.
+
+Supported capabilities of specific counter_desc values per verbs object can be
+tested by checking the return value for success or ENOTSUP errno.
+
+Attaching a counters handle to multiple objects of the same type will accumulate
+the values into a single index. e.g.: creating several ibv_flows with the same
+ibv_counters handle will collect the values from all relevant flows into the
+relevant index location when reading the values from **ibv_read_counters**(),
+setting the index more than once with different or same counter_desc will
+aggregate the values from all relevant counters into the relevant index
+location.
+
+The runtime values of counters can be read from the hardware by calling
+**ibv_read_counters**().
+
+# ARGUMENTS
+
+*counters*
+:	Existing counters to attach new counter point on.
+
+*counter_attach_attr*
+:	An ibv_counter_attach_attr struct, as defined in verbs.h.
+
+*flow*
+:	Existing flow to attach a new counters point on (in static mode
+it must be NULL).
+
+## *counter_attach_attr* Argument
+
+```c
+struct ibv_counter_attach_attr {
+	enum ibv_counter_description counter_desc;
+	uint32_t index;
+	uint32_t comp_mask;
+};
+```
+
+## *counter_desc* Argument
+
+```c
+enum ibv_counter_description {
+	IBV_COUNTER_PACKETS,
+	IBV_COUNTER_BYTES,
+};
+```
+
+*index*
+:	Desired location of the specific counter at the counters object.
+
+*comp_mask*
+:	Bitmask specifying what fields in the structure are valid.
+
+# RETURN VALUE
+
+**ibv_attach_counters_point_flow**() returns 0 on success, or the value of errno
+on failure (which indicates the failure reason)
+
+# ERRORS
+
+EINVAL
+:	invalid argument(s) passed
+
+ENOTSUP
+:	*counter_desc* is not supported on the requested object
+
+EBUSY
+:	the counter object is already bound to a flow, additional attach calls is not allowed (valid for static attach only)
+
+ENOMEM
+:	not enough memory
+
+# NOTES
+Counter values in each index location are cleared upon creation when calling
+**ibv_create_counters**().
+Attaching counters points will only increase these values accordingly.
+
+# EXAMPLE
+
+An example of use of **ibv_attach_counters_point_flow**() is shown in
+**ibv_read_counters**(3)
+
+# SEE ALSO
+
+**ibv_create_counters**(3), **ibv_destroy_counters**(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 6eceadc..066396f 100644
--- a/libibverbs/verbs.h
+++ b/libibverbs/verbs.h
@@ -1726,6 +1726,17 @@ struct ibv_counters {
 	struct ibv_context	*context;
 };
 
+enum ibv_counter_description {
+	IBV_COUNTER_PACKETS,
+	IBV_COUNTER_BYTES,
+};
+
+struct ibv_counter_attach_attr {
+	enum ibv_counter_description counter_desc;
+	uint32_t index; /* Desired location index of the counter at the counters object */
+	uint32_t comp_mask;
+};
+
 enum ibv_values_mask {
 	IBV_VALUES_MASK_RAW_CLOCK	= 1 << 0,
 	IBV_VALUES_MASK_RESERVED	= 1 << 1
@@ -1738,6 +1749,9 @@ struct ibv_values_ex {
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	int (*attach_counters_point_flow)(struct ibv_counters *counters,
+					  struct ibv_counter_attach_attr *attr,
+					  struct ibv_flow *flow);
 	struct ibv_counters *(*create_counters)(struct ibv_context *context,
 						struct ibv_counters_init_attr *init_attr);
 	int (*destroy_counters)(struct ibv_counters *counters);
@@ -2833,6 +2847,19 @@ static inline int ibv_destroy_counters(struct ibv_counters *counters)
 	return vctx->destroy_counters(counters);
 }
 
+static inline int ibv_attach_counters_point_flow(struct ibv_counters *counters,
+						 struct ibv_counter_attach_attr *attr,
+						 struct ibv_flow *flow)
+{
+	struct verbs_context *vctx;
+
+	vctx = verbs_get_ctx_op(counters->context, attach_counters_point_flow);
+	if (!vctx)
+		return ENOSYS;
+
+	return vctx->attach_counters_point_flow(counters, attr, flow);
+}
+
 #ifdef __cplusplus
 }
 #endif
