[1/3] reorder: add new drain up to seq number API

Message ID 20230120102146.4035460-2-vfialko@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series reorder: introduce new APIs |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Volodymyr Fialko Jan. 20, 2023, 10:21 a.m. UTC
  Introduce new reorder drain API:
`rte_reorder_drain_up_to_seqn` - exhaustively drain all inserted mbufs
up to the given sequence number.

Currently there's no ability to force the drain from reorder buffer,
i.e. only consecutive ordered or ready packets could be drained.
New function would give user ability to drain inserted packets, without
need to wait for missing or newer packets.

Signed-off-by: Volodymyr Fialko <vfialko@marvell.com>
---
 lib/reorder/rte_reorder.c | 77 +++++++++++++++++++++++++++++++++++++++
 lib/reorder/rte_reorder.h | 25 +++++++++++++
 lib/reorder/version.map   |  1 +
 3 files changed, 103 insertions(+)
  

Comments

Thomas Monjalon Feb. 19, 2023, 11:30 p.m. UTC | #1
We are waiting for a detailed review.
The series could be merged without review.

Please fix cosmetic comments below and send a new version to check CI result.

20/01/2023 11:21, Volodymyr Fialko:
> Introduce new reorder drain API:
> `rte_reorder_drain_up_to_seqn` - exhaustively drain all inserted mbufs
> up to the given sequence number.
> 
> Currently there's no ability to force the drain from reorder buffer,
> i.e. only consecutive ordered or ready packets could be drained.
> New function would give user ability to drain inserted packets, without
> need to wait for missing or newer packets.
> 
> Signed-off-by: Volodymyr Fialko <vfialko@marvell.com>
[...]
> --- a/lib/reorder/rte_reorder.h
> +++ b/lib/reorder/rte_reorder.h
> @@ -167,6 +167,31 @@ unsigned int
>  rte_reorder_drain(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs,
>  		unsigned max_mbufs);
>  
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * Fetch set of reordered packets up to specified sequence number (exclusive)
> + *
> + * Returns a set of in-order packets from the reorder buffer structure.
> + * Gaps may be present since reorder buffer will try to fetch all possible packets up to given
> + * sequence number.
> + *
> + * @param b
> + *   Reorder buffer instance from which packets are to be drained.
> + * @param mbufs
> + *   Array of mbufs where reordered packets will be inserted from reorder buffer.
> + * @param max_mbufs
> + *   The number of elements in the mbufs array.
> + * @param seqn
> + *   Sequence number up to which buffer will be drained.
> + * @return
> + *   Number of mbuf pointers written to mbufs. 0 <= N < max_mbufs.
> + */
> +__rte_experimental
> +unsigned int
> +rte_reorder_drain_up_to_seqn(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs,
> +		unsigned int max_mbufs, rte_reorder_seqn_t seqn);
>  #ifdef __cplusplus

blank line missing

> --- a/lib/reorder/version.map
> +++ b/lib/reorder/version.map
> @@ -16,4 +16,5 @@ EXPERIMENTAL {
>  	global:
>  
>  	rte_reorder_seqn_dynfield_offset;
> +	rte_reorder_drain_up_to_seqn;

Please add a comment "# added in 23.03" as we do in other libs.
  

Patch

diff --git a/lib/reorder/rte_reorder.c b/lib/reorder/rte_reorder.c
index 385ee479da..57cc1b286b 100644
--- a/lib/reorder/rte_reorder.c
+++ b/lib/reorder/rte_reorder.c
@@ -406,3 +406,80 @@  rte_reorder_drain(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs,
 
 	return drain_cnt;
 }
+
+/* Binary search seqn in ready buffer */
+static inline uint32_t
+ready_buffer_seqn_find(const struct cir_buffer *ready_buf, const uint32_t seqn)
+{
+	uint32_t mid, value, position, high;
+	uint32_t low = 0;
+
+	if (ready_buf->tail > ready_buf->head)
+		high = ready_buf->tail - ready_buf->head;
+	else
+		high = ready_buf->head - ready_buf->tail;
+
+	while (low <= high) {
+		mid = low + (high - low) / 2;
+		position = (ready_buf->tail + mid) & ready_buf->mask;
+		value = *rte_reorder_seqn(ready_buf->entries[position]);
+		if (seqn == value)
+			return mid;
+		else if (seqn > value)
+			low = mid + 1;
+		else
+			high = mid - 1;
+	}
+
+	return low;
+}
+
+unsigned int
+rte_reorder_drain_up_to_seqn(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs,
+		const unsigned int max_mbufs, const rte_reorder_seqn_t seqn)
+{
+	uint32_t i, position, offset;
+	unsigned int drain_cnt = 0;
+
+	struct cir_buffer *order_buf = &b->order_buf,
+			*ready_buf = &b->ready_buf;
+
+	/* Seqn in Ready buffer */
+	if (seqn < b->min_seqn) {
+		/* All sequence numbers are higher then given */
+		if (*rte_reorder_seqn(ready_buf->entries[ready_buf->tail]) > seqn)
+			return 0;
+
+		offset = ready_buffer_seqn_find(ready_buf, seqn);
+
+		for (i = 0; (i < offset) && (drain_cnt < max_mbufs); i++) {
+			position = (ready_buf->tail + i) & ready_buf->mask;
+			mbufs[drain_cnt++] = ready_buf->entries[position];
+			ready_buf->entries[position] = NULL;
+		}
+		ready_buf->tail = (ready_buf->tail + i) & ready_buf->mask;
+
+		return drain_cnt;
+	}
+
+	/* Seqn in Order buffer, add all buffers from Ready buffer */
+	while ((drain_cnt < max_mbufs) && (ready_buf->tail != ready_buf->head)) {
+		mbufs[drain_cnt++] = ready_buf->entries[ready_buf->tail];
+		ready_buf->entries[ready_buf->tail] = NULL;
+		ready_buf->tail = (ready_buf->tail + 1) & ready_buf->mask;
+	}
+
+	/* Fetch buffers from Order buffer up to given sequence number (exclusive) */
+	offset = RTE_MIN(seqn - b->min_seqn, b->order_buf.size);
+	for (i = 0; (i < offset) && (drain_cnt < max_mbufs); i++) {
+		position = (order_buf->head + i) & order_buf->mask;
+		if (order_buf->entries[position] == NULL)
+			continue;
+		mbufs[drain_cnt++] = order_buf->entries[position];
+		order_buf->entries[position] = NULL;
+	}
+	b->min_seqn += i;
+	order_buf->head = (order_buf->head + i) & order_buf->mask;
+
+	return drain_cnt;
+}
diff --git a/lib/reorder/rte_reorder.h b/lib/reorder/rte_reorder.h
index 5abdb258e2..c5b354b53d 100644
--- a/lib/reorder/rte_reorder.h
+++ b/lib/reorder/rte_reorder.h
@@ -167,6 +167,31 @@  unsigned int
 rte_reorder_drain(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs,
 		unsigned max_mbufs);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Fetch set of reordered packets up to specified sequence number (exclusive)
+ *
+ * Returns a set of in-order packets from the reorder buffer structure.
+ * Gaps may be present since reorder buffer will try to fetch all possible packets up to given
+ * sequence number.
+ *
+ * @param b
+ *   Reorder buffer instance from which packets are to be drained.
+ * @param mbufs
+ *   Array of mbufs where reordered packets will be inserted from reorder buffer.
+ * @param max_mbufs
+ *   The number of elements in the mbufs array.
+ * @param seqn
+ *   Sequence number up to which buffer will be drained.
+ * @return
+ *   Number of mbuf pointers written to mbufs. 0 <= N < max_mbufs.
+ */
+__rte_experimental
+unsigned int
+rte_reorder_drain_up_to_seqn(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs,
+		unsigned int max_mbufs, rte_reorder_seqn_t seqn);
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/reorder/version.map b/lib/reorder/version.map
index e114d17730..e3f41ea7ef 100644
--- a/lib/reorder/version.map
+++ b/lib/reorder/version.map
@@ -16,4 +16,5 @@  EXPERIMENTAL {
 	global:
 
 	rte_reorder_seqn_dynfield_offset;
+	rte_reorder_drain_up_to_seqn;
 };