[1/3] reorder: add new drain up to seq number API
Checks
Commit Message
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
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.
@@ -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;
+}
@@ -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
@@ -16,4 +16,5 @@ EXPERIMENTAL {
global:
rte_reorder_seqn_dynfield_offset;
+ rte_reorder_drain_up_to_seqn;
};