lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 31 Jan 2018 14:53:44 +0100
From:   Björn Töpel <bjorn.topel@...il.com>
To:     bjorn.topel@...il.com, magnus.karlsson@...el.com,
        alexander.h.duyck@...el.com, alexander.duyck@...il.com,
        john.fastabend@...il.com, ast@...com, brouer@...hat.com,
        willemdebruijn.kernel@...il.com, daniel@...earbox.net,
        netdev@...r.kernel.org
Cc:     Björn Töpel <bjorn.topel@...el.com>,
        michael.lundkvist@...csson.com, jesse.brandeburg@...el.com,
        anjali.singhai@...el.com, jeffrey.b.shaw@...el.com,
        ferruh.yigit@...el.com, qi.z.zhang@...el.com
Subject: [RFC PATCH 12/24] xsk: add iterator functions to xsk_ring

From: Björn Töpel <bjorn.topel@...el.com>

Add packet array like functionality that acts directly on the
user/kernel shared ring. We'll use this in the zerocopy Rx scenario.

TODO Better naming...

Signed-off-by: Björn Töpel <bjorn.topel@...el.com>
---
 net/xdp/xsk_ring.c |   3 +-
 net/xdp/xsk_ring.h | 136 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 126 insertions(+), 13 deletions(-)

diff --git a/net/xdp/xsk_ring.c b/net/xdp/xsk_ring.c
index 11b590506ddf..f154ddfabcfc 100644
--- a/net/xdp/xsk_ring.c
+++ b/net/xdp/xsk_ring.c
@@ -41,7 +41,8 @@ struct xsk_queue *xskq_create(u32 nentries)
 	q->queue_ops.enqueue = xskq_enqueue_from_array;
 	q->queue_ops.enqueue_completed = xskq_enqueue_completed_from_array;
 	q->queue_ops.dequeue = xskq_dequeue_to_array;
-	q->used_idx = 0;
+	q->used_idx_head = 0;
+	q->used_idx_tail = 0;
 	q->last_avail_idx = 0;
 	q->ring_mask = nentries - 1;
 	q->num_free = 0;
diff --git a/net/xdp/xsk_ring.h b/net/xdp/xsk_ring.h
index c9d61195ab2d..43c841d55093 100644
--- a/net/xdp/xsk_ring.h
+++ b/net/xdp/xsk_ring.h
@@ -27,7 +27,8 @@ struct xsk_queue {
 	struct xsk_user_queue queue_ops;
 	struct xdp_desc *ring;
 
-	u32 used_idx;
+	u32 used_idx_head;
+	u32 used_idx_tail;
 	u32 last_avail_idx;
 	u32 ring_mask;
 	u32 num_free;
@@ -51,8 +52,7 @@ static inline unsigned int xsk_get_data_headroom(struct xsk_umem *umem)
  *
  * Returns true if the entry is a valid, otherwise false
  **/
-static inline bool xskq_is_valid_entry(struct xsk_queue *q,
-				       struct xdp_desc *d)
+static inline bool xskq_is_valid_entry(struct xsk_queue *q, struct xdp_desc *d)
 {
 	unsigned int buff_len;
 
@@ -115,7 +115,7 @@ static inline int xskq_nb_avail(struct xsk_queue *q, int dcnt)
 static inline int xskq_enqueue(struct xsk_queue *q,
 			       const struct xdp_desc *d, int dcnt)
 {
-	unsigned int used_idx = q->used_idx;
+	unsigned int used_idx = q->used_idx_tail;
 	int i;
 
 	if (q->num_free < dcnt)
@@ -136,11 +136,12 @@ static inline int xskq_enqueue(struct xsk_queue *q,
 	smp_wmb();
 
 	for (i = dcnt - 1; i >= 0; i--) {
-		unsigned int idx = (q->used_idx + i) & q->ring_mask;
+		unsigned int idx = (q->used_idx_tail + i) & q->ring_mask;
 
 		q->ring[idx].flags = d[i].flags & ~XDP_DESC_KERNEL;
 	}
-	q->used_idx += dcnt;
+	q->used_idx_head += dcnt;
+	q->used_idx_tail += dcnt;
 
 	return 0;
 }
@@ -157,7 +158,7 @@ static inline int xskq_enqueue_from_array(struct xsk_packet_array *a,
 					  u32 dcnt)
 {
 	struct xsk_queue *q = (struct xsk_queue *)a->q_ops;
-	unsigned int used_idx = q->used_idx;
+	unsigned int used_idx = q->used_idx_tail;
 	struct xdp_desc *d = a->items;
 	int i;
 
@@ -180,12 +181,13 @@ static inline int xskq_enqueue_from_array(struct xsk_packet_array *a,
 	smp_wmb();
 
 	for (i = dcnt - 1; i >= 0; i--) {
-		unsigned int idx = (q->used_idx + i) & q->ring_mask;
+		unsigned int idx = (q->used_idx_tail + i) & q->ring_mask;
 		unsigned int didx = (a->start + i) & a->mask;
 
 		q->ring[idx].flags = d[didx].flags & ~XDP_DESC_KERNEL;
 	}
-	q->used_idx += dcnt;
+	q->used_idx_tail += dcnt;
+	q->used_idx_head += dcnt;
 
 	return 0;
 }
@@ -204,7 +206,7 @@ static inline int xskq_enqueue_completed_from_array(struct xsk_packet_array *a,
 						    u32 dcnt)
 {
 	struct xsk_queue *q = (struct xsk_queue *)a->q_ops;
-	unsigned int used_idx = q->used_idx;
+	unsigned int used_idx = q->used_idx_tail;
 	struct xdp_desc *d = a->items;
 	int i, j;
 
@@ -233,13 +235,14 @@ static inline int xskq_enqueue_completed_from_array(struct xsk_packet_array *a,
 	smp_wmb();
 
 	for (j = i - 1; j >= 0; j--) {
-		unsigned int idx = (q->used_idx + j) & q->ring_mask;
+		unsigned int idx = (q->used_idx_tail + j) & q->ring_mask;
 		unsigned int didx = (a->start + j) & a->mask;
 
 		q->ring[idx].flags = d[didx].flags & ~XDP_DESC_KERNEL;
 	}
 	q->num_free -= i;
-	q->used_idx += i;
+	q->used_idx_tail += i;
+	q->used_idx_head += i;
 
 	return i;
 }
@@ -301,6 +304,115 @@ static inline void xskq_set_buff_info(struct xsk_queue *q,
 	q->validation = validation;
 }
 
+/* --- */
+
+struct xskq_iter {
+	unsigned int head;
+	unsigned int tail;
+};
+
+static inline bool xskq_iter_end(struct xskq_iter *it)
+{
+	return it->tail == it->head;
+}
+
+static inline void xskq_iter_validate(struct xsk_queue *q, struct xskq_iter *it)
+{
+	while (it->head != it->tail) {
+		unsigned int idx = it->head & q->ring_mask;
+		struct xdp_desc *d, *du;
+
+		d = &q->ring[idx];
+		if (xskq_is_valid_entry(q, d))
+			break;
+
+		/* Slow error path! */
+		du = &q->ring[q->used_idx_tail & q->ring_mask];
+		du->idx = d->idx;
+		du->len = d->len;
+		du->offset = d->offset;
+		du->error = EINVAL;
+
+		q->last_avail_idx++;
+		it->head++;
+
+		smp_wmb();
+
+		du->flags = d->flags & ~XDP_DESC_KERNEL;
+	}
+}
+
+static inline struct xskq_iter xskq_deq_iter(struct xsk_queue *q,
+					     int cnt)
+{
+	struct xskq_iter it;
+
+	it.head = q->last_avail_idx;
+	it.tail = it.head + (unsigned int)xskq_nb_avail(q, cnt);
+
+	smp_rmb();
+
+	xskq_iter_validate(q, &it);
+
+	return it;
+}
+
+static inline void xskq_deq_iter_next(struct xsk_queue *q, struct xskq_iter *it)
+{
+	it->head++;
+	xskq_iter_validate(q, it);
+}
+
+static inline void xskq_deq_iter_done(struct xsk_queue *q, struct xskq_iter *it)
+{
+	int entries = it->head - q->last_avail_idx;
+
+	q->num_free += entries;
+	q->last_avail_idx = it->head;
+}
+
+static inline u32 xskq_deq_iter_get_id(struct xsk_queue *q,
+				       struct xskq_iter *it)
+{
+	return q->ring[it->head & q->ring_mask].idx;
+}
+
+static inline void xskq_return_id(struct xsk_queue *q, u32 id)
+{
+	struct xdp_desc d = { .idx = id };
+
+	WARN(xskq_enqueue(q, &d, 1), "%s failed!\n", __func__);
+}
+
+static inline void xskq_enq_lazy(struct xsk_queue *q,
+				 u32 id, u32 len, u16 offset)
+{
+	unsigned int idx;
+
+	if (q->num_free == 0) {
+		WARN(1, "%s xsk_queue deq/enq out of sync!\n", __func__);
+		return;
+	}
+
+	q->num_free--;
+	idx = (q->used_idx_tail++) & q->ring_mask;
+	q->ring[idx].idx = id;
+	q->ring[idx].len = len;
+	q->ring[idx].offset = offset;
+	q->ring[idx].error = 0;
+}
+
+static inline void xskq_enq_flush(struct xsk_queue *q)
+{
+	smp_wmb();
+
+	while (q->used_idx_head != q->used_idx_tail) {
+		unsigned int idx = (q->used_idx_head++) & q->ring_mask;
+
+		q->ring[idx].flags = 0;
+	}
+}
+
 struct xsk_queue *xskq_create(u32 nentries);
 void xskq_destroy(struct xsk_queue *q_ops);
 
-- 
2.14.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ