From: Björn Töpel <hidden> Date: 2021-03-01 10:44:44
This two-patch series introduces load-acquire/store-release semantics
for the AF_XDP rings.
For most contemporary architectures, this is more effective than a
SPSC ring based on smp_{r,w,}mb() barriers. More importantly,
load-acquire/store-release semantics make the ring code easier to
follow.
This is effectively the change done in commit 6c43c091bdc5
("documentation: Update circular buffer for
load-acquire/store-release"), but for the AF_XDP rings.
Both libbpf and the kernel-side are updated.
More details in each commit.
Thanks,
Björn
Björn Töpel (2):
xsk: update rings for load-acquire/store-release semantics
libbpf, xsk: add libbpf_smp_store_release libbpf_smp_load_acquire
net/xdp/xsk_queue.h | 27 ++++++--------
tools/lib/bpf/libbpf_util.h | 72 +++++++++++++++++++++++++------------
tools/lib/bpf/xsk.h | 17 +++------
3 files changed, 66 insertions(+), 50 deletions(-)
base-commit: 85e142cb42a1e7b33971bf035dae432d8670c46b
--
2.27.0
From: Björn Töpel <hidden> Date: 2021-03-01 10:44:44
From: Björn Töpel <redacted>
Currently, the AF_XDP rings uses smp_{r,w,}mb() fences on the
kernel-side. By updating the rings for load-acquire/store-release
semantics, the full barrier on the consumer side can be replaced with
improved performance as a nice side-effect.
Note that this change does *not* require similar changes on the
libbpf/userland side, however it is recommended [1].
On x86-64 systems, by removing the smp_mb() on the Rx and Tx side, the
l2fwd AF_XDP xdpsock sample performance increases by
1%. Weakly-ordered platforms, such as ARM64 might benefit even more.
[1] https://lore.kernel.org/bpf/20200316184423.GA14143@willie-the-truck/
Signed-off-by: Björn Töpel <redacted>
---
net/xdp/xsk_queue.h | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
@@ -47,19 +47,18 @@ struct xsk_queue {u64queue_empty_descs;};-/* The structure of the shared state of the rings are the same as the-*ringbufferinkernel/events/ring_buffer.c.FortheRxandcompletion-*ring,thekernelistheproduceranduserspaceistheconsumer.For-*theTxandfillrings,thekernelistheconsumeranduserspaceis-*theproducer.+/* The structure of the shared state of the rings are a simple+*circularbuffer,asoutlinedin+*Documentation/core-api/circular-buffers.rst.FortheRxand+*completionring,thekernelistheproduceranduserspaceisthe+*consumer.FortheTxandfillrings,thekernelistheconsumerand+*userspaceistheproducer.**producerconsumer*-*if(LOAD->consumer){LOAD->producer-*(A)smp_rmb()(C)+*if(LOAD->consumer){(A)LOAD.acq->producer(C)*STORE$dataLOAD$data-*smp_wmb()(B)smp_mb()(D)-*STORE->producerSTORE->consumer+*STORE.rel->producer(B)STORE.rel->consumer(D)*}**(A)pairswith(D),and(B)pairswith(C).
@@ -227,15 +226,13 @@ static inline u32 xskq_cons_read_desc_batch(struct xsk_queue *q,staticinlinevoid__xskq_cons_release(structxsk_queue*q){-smp_mb();/* D, matches A */-WRITE_ONCE(q->ring->consumer,q->cached_cons);+smp_store_release(&q->ring->consumer,q->cached_cons);/* D, matchees A */}staticinlinevoid__xskq_cons_peek(structxsk_queue*q){/* Refresh the local pointer */-q->cached_prod=READ_ONCE(q->ring->producer);-smp_rmb();/* C, matches B */+q->cached_prod=smp_load_acquire(&q->ring->producer);/* C, matches B */}staticinlinevoidxskq_cons_get_entries(structxsk_queue*q)
@@ -397,9 +394,7 @@ static inline int xskq_prod_reserve_desc(struct xsk_queue *q,staticinlinevoid__xskq_prod_submit(structxsk_queue*q,u32idx){-smp_wmb();/* B, matches C */--WRITE_ONCE(q->ring->producer,idx);+smp_store_release(&q->ring->producer,idx);/* B, matches C */}staticinlinevoidxskq_prod_submit(structxsk_queue*q)
From: Björn Töpel <hidden> Date: 2021-03-01 10:44:45
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
Signed-off-by: Björn Töpel <redacted>
---
tools/lib/bpf/libbpf_util.h | 72 +++++++++++++++++++++++++------------
tools/lib/bpf/xsk.h | 17 +++------
2 files changed, 55 insertions(+), 34 deletions(-)
@@ -129,9 +130,7 @@ static inline void xsk_ring_prod__submit(struct xsk_ring_prod *prod, __u32 nb)/* Make sure everything has been written to the ring before indicating*thistothekernelbywritingtheproducerpointer.*/-libbpf_smp_wmb();--*prod->producer+=nb;+libbpf_smp_store_release(prod->producer,*prod->producer+nb);}staticinline__u32xsk_ring_cons__peek(structxsk_ring_cons*cons,__u32nb,__u32*idx)
@@ -139,11 +138,6 @@ static inline __u32 xsk_ring_cons__peek(struct xsk_ring_cons *cons, __u32 nb, ____u32entries=xsk_cons_nb_avail(cons,nb);if(entries>0){-/* Make sure we do not speculatively read the data before-*wehavereceivedthepacketbuffersfromthering.-*/-libbpf_smp_rmb();-*idx=cons->cached_cons;cons->cached_cons+=entries;}
@@ -161,9 +155,8 @@ static inline void xsk_ring_cons__release(struct xsk_ring_cons *cons, __u32 nb)/* Make sure data has been read before indicating we are done*withtheentriesbyupdatingtheconsumerpointer.*/-libbpf_smp_rwmb();+libbpf_smp_store_release(cons->consumer,*cons->consumer+nb);-*cons->consumer+=nb;}staticinlinevoid*xsk_umem__get_data(void*umem_area,__u64addr)
From: Björn Töpel <redacted>
Currently, the AF_XDP rings uses smp_{r,w,}mb() fences on the
kernel-side. By updating the rings for load-acquire/store-release
semantics, the full barrier on the consumer side can be replaced with
improved performance as a nice side-effect.
Note that this change does *not* require similar changes on the
libbpf/userland side, however it is recommended [1].
On x86-64 systems, by removing the smp_mb() on the Rx and Tx side, the
l2fwd AF_XDP xdpsock sample performance increases by
1%. Weakly-ordered platforms, such as ARM64 might benefit even more.
[1] https://lore.kernel.org/bpf/20200316184423.GA14143@willie-the-truck/
Signed-off-by: Björn Töpel <redacted>
---
net/xdp/xsk_queue.h | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
@@ -47,19 +47,18 @@ struct xsk_queue {u64queue_empty_descs;};-/* The structure of the shared state of the rings are the same as the-*ringbufferinkernel/events/ring_buffer.c.FortheRxandcompletion-*ring,thekernelistheproduceranduserspaceistheconsumer.For-*theTxandfillrings,thekernelistheconsumeranduserspaceis-*theproducer.+/* The structure of the shared state of the rings are a simple+*circularbuffer,asoutlinedin+*Documentation/core-api/circular-buffers.rst.FortheRxand+*completionring,thekernelistheproduceranduserspaceisthe+*consumer.FortheTxandfillrings,thekernelistheconsumerand+*userspaceistheproducer.**producerconsumer*-*if(LOAD->consumer){LOAD->producer-*(A)smp_rmb()(C)+*if(LOAD->consumer){(A)LOAD.acq->producer(C)
Why is LOAD.acq not needed on the consumer side?
-Toke
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
So what happens if an updated libbpf is paired with an older kernel (or
vice versa)?
-Toke
From: Björn Töpel <hidden> Date: 2021-03-02 10:39:12
On 2021-03-01 17:10, Toke Høiland-Jørgensen wrote:
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
So what happens if an updated libbpf is paired with an older kernel (or
vice versa)?
From: Björn Töpel <hidden> Date: 2021-03-02 10:39:12
On 2021-03-01 17:08, Toke Høiland-Jørgensen wrote:
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Currently, the AF_XDP rings uses smp_{r,w,}mb() fences on the
kernel-side. By updating the rings for load-acquire/store-release
semantics, the full barrier on the consumer side can be replaced with
improved performance as a nice side-effect.
Note that this change does *not* require similar changes on the
libbpf/userland side, however it is recommended [1].
On x86-64 systems, by removing the smp_mb() on the Rx and Tx side, the
l2fwd AF_XDP xdpsock sample performance increases by
1%. Weakly-ordered platforms, such as ARM64 might benefit even more.
[1] https://lore.kernel.org/bpf/20200316184423.GA14143@willie-the-truck/
Signed-off-by: Björn Töpel <redacted>
---
net/xdp/xsk_queue.h | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
@@ -47,19 +47,18 @@ struct xsk_queue {u64queue_empty_descs;};-/* The structure of the shared state of the rings are the same as the-*ringbufferinkernel/events/ring_buffer.c.FortheRxandcompletion-*ring,thekernelistheproduceranduserspaceistheconsumer.For-*theTxandfillrings,thekernelistheconsumeranduserspaceis-*theproducer.+/* The structure of the shared state of the rings are a simple+*circularbuffer,asoutlinedin+*Documentation/core-api/circular-buffers.rst.FortheRxand+*completionring,thekernelistheproduceranduserspaceisthe+*consumer.FortheTxandfillrings,thekernelistheconsumerand+*userspaceistheproducer.**producerconsumer*-*if(LOAD->consumer){LOAD->producer-*(A)smp_rmb()(C)+*if(LOAD->consumer){(A)LOAD.acq->producer(C)
Why is LOAD.acq not needed on the consumer side?
You mean why LOAD.acq is not needed on the *producer* side, i.e. the
->consumer? The ->consumer is a control dependency for the store, so
there is no ordering constraint for ->consumer at producer side. If
there's no space, no data is written. So, no barrier is needed there --
at least that has been my perspective.
This is very similar to the buffer in
Documentation/core-api/circular-buffers.rst. Roping in Paul for some
guidance.
Björn
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2021-03-02 10:39:13
On 3/2/21 9:05 AM, Björn Töpel wrote:
On 2021-03-01 17:10, Toke Høiland-Jørgensen wrote:
quoted
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
So what happens if an updated libbpf is paired with an older kernel (or
vice versa)?
"This is fine." ;-) This was briefly discussed in [1], outlined by the
previous commit!
...even on POWER.
Could you put a summary or quote of that discussion on 'why it is okay and does not
cause /forward or backward/ compat issues with user space' directly into patch 1's
commit message?
I feel just referring to a link is probably less suitable in this case as it should
rather be part of the commit message that contains the justification on why it is
waterproof - at least it feels that specific area may be a bit under-documented, so
having it as direct part certainly doesn't hurt.
Would also be great to get Will's ACK on that when you have a v2. :)
Thanks,
Daniel
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2021-03-02 10:39:13
On 3/2/21 10:16 AM, Björn Töpel wrote:
On 2021-03-02 10:13, Daniel Borkmann wrote:
quoted
On 3/2/21 9:05 AM, Björn Töpel wrote:
quoted
On 2021-03-01 17:10, Toke Høiland-Jørgensen wrote:
quoted
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
So what happens if an updated libbpf is paired with an older kernel (or
vice versa)?
"This is fine." ;-) This was briefly discussed in [1], outlined by the
previous commit!
...even on POWER.
Could you put a summary or quote of that discussion on 'why it is okay and does not
cause /forward or backward/ compat issues with user space' directly into patch 1's
commit message?
I feel just referring to a link is probably less suitable in this case as it should
rather be part of the commit message that contains the justification on why it is
waterproof - at least it feels that specific area may be a bit under-documented, so
having it as direct part certainly doesn't hurt.
I agree; It's enough in the weed as it is already.
I wonder if it's possible to cook a LKMM litmus test for this...?
That would be amazing! :-)
(Another option which can be done independently could be to update [0] with outlining a
pairing scenario as we have here describing the forward/backward compatibility on the
barriers used, I think that would be quite useful as well.)
[0] Documentation/memory-barriers.txt
quoted
Would also be great to get Will's ACK on that when you have a v2. :)
From: Björn Töpel <hidden> Date: 2021-03-02 10:39:13
On 2021-03-02 10:13, Daniel Borkmann wrote:
On 3/2/21 9:05 AM, Björn Töpel wrote:
quoted
On 2021-03-01 17:10, Toke Høiland-Jørgensen wrote:
quoted
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
So what happens if an updated libbpf is paired with an older kernel (or
vice versa)?
"This is fine." ;-) This was briefly discussed in [1], outlined by the
previous commit!
...even on POWER.
Could you put a summary or quote of that discussion on 'why it is okay
and does not
cause /forward or backward/ compat issues with user space' directly into
patch 1's
commit message?
I feel just referring to a link is probably less suitable in this case
as it should
rather be part of the commit message that contains the justification on
why it is
waterproof - at least it feels that specific area may be a bit
under-documented, so
having it as direct part certainly doesn't hurt.
I agree; It's enough in the weed as it is already.
I wonder if it's possible to cook a LKMM litmus test for this...?
Would also be great to get Will's ACK on that when you have a v2. :)
On 2021-03-01 17:08, Toke Høiland-Jørgensen wrote:
quoted
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Currently, the AF_XDP rings uses smp_{r,w,}mb() fences on the
kernel-side. By updating the rings for load-acquire/store-release
semantics, the full barrier on the consumer side can be replaced with
improved performance as a nice side-effect.
Note that this change does *not* require similar changes on the
libbpf/userland side, however it is recommended [1].
On x86-64 systems, by removing the smp_mb() on the Rx and Tx side, the
l2fwd AF_XDP xdpsock sample performance increases by
1%. Weakly-ordered platforms, such as ARM64 might benefit even more.
[1] https://lore.kernel.org/bpf/20200316184423.GA14143@willie-the-truck/
Signed-off-by: Björn Töpel <redacted>
---
net/xdp/xsk_queue.h | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
@@ -47,19 +47,18 @@ struct xsk_queue {u64queue_empty_descs;};-/* The structure of the shared state of the rings are the same as the-*ringbufferinkernel/events/ring_buffer.c.FortheRxandcompletion-*ring,thekernelistheproduceranduserspaceistheconsumer.For-*theTxandfillrings,thekernelistheconsumeranduserspaceis-*theproducer.+/* The structure of the shared state of the rings are a simple+*circularbuffer,asoutlinedin+*Documentation/core-api/circular-buffers.rst.FortheRxand+*completionring,thekernelistheproduceranduserspaceisthe+*consumer.FortheTxandfillrings,thekernelistheconsumerand+*userspaceistheproducer.**producerconsumer*-*if(LOAD->consumer){LOAD->producer-*(A)smp_rmb()(C)+*if(LOAD->consumer){(A)LOAD.acq->producer(C)
Why is LOAD.acq not needed on the consumer side?
You mean why LOAD.acq is not needed on the *producer* side, i.e. the
->consumer?
Yes, of course! The two words were, like, right next to each other ;)
The ->consumer is a control dependency for the store, so there is no
ordering constraint for ->consumer at producer side. If there's no
space, no data is written. So, no barrier is needed there -- at least
that has been my perspective.
This is very similar to the buffer in
Documentation/core-api/circular-buffers.rst. Roping in Paul for some
guidance.
Yeah, I did read that, but got thrown off by this bit: "Therefore, the
unlock-lock pair between consecutive invocations of the consumer
provides the necessary ordering between the read of the index indicating
that the consumer has vacated a given element and the write by the
producer to that same element."
Since there is no lock in the XSK, what provides that guarantee here?
Oh, and BTW, when I re-read the rest of the comment in xsk_queue.h
(below the diagram you are changing in this patch), the text still talks
about "memory barriers" - maybe that should be updated to
release/acquire as well while you're changing things?
-Toke
On Mon, Mar 1, 2021 at 2:43 AM Björn Töpel [off-list ref] wrote:
quoted hunk
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
Signed-off-by: Björn Töpel <redacted>
---
tools/lib/bpf/libbpf_util.h | 72 +++++++++++++++++++++++++------------
tools/lib/bpf/xsk.h | 17 +++------
2 files changed, 55 insertions(+), 34 deletions(-)
So, technically, these four are part of libbpf's API, as libbpf_util.h
is actually installed on target hosts. Seems like xsk.h is the only
one that is using them, though.
So the question is whether it's ok to remove them now?
And also, why wasn't this part of xsk.h in the first place?
From: Björn Töpel <hidden> Date: 2021-03-03 22:55:56
On 2021-03-03 05:38, Andrii Nakryiko wrote:
On Mon, Mar 1, 2021 at 2:43 AM Björn Töpel [off-list ref] wrote:
quoted
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
Signed-off-by: Björn Töpel <redacted>
---
tools/lib/bpf/libbpf_util.h | 72 +++++++++++++++++++++++++------------
tools/lib/bpf/xsk.h | 17 +++------
2 files changed, 55 insertions(+), 34 deletions(-)
So, technically, these four are part of libbpf's API, as libbpf_util.h
is actually installed on target hosts. Seems like xsk.h is the only
one that is using them, though.
So the question is whether it's ok to remove them now?
I would say that. Ideally, the barriers shouldn't be visible at all,
since they're only used as an implementation detail for the static
inline functions.
And also, why wasn't this part of xsk.h in the first place?
I guess there was a "maybe it can be useful for more than the XDP socket
parts of libbpf"-idea. I'll move them to xsk.h for the v2, which will
make the migration easier.
Björn
From: Björn Töpel <hidden> Date: 2021-03-03 22:56:50
On Tue, 2 Mar 2021 at 11:23, Toke Høiland-Jørgensen [off-list ref] wrote:
Björn Töpel [off-list ref] writes:
quoted
On 2021-03-01 17:08, Toke Høiland-Jørgensen wrote:
quoted
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Currently, the AF_XDP rings uses smp_{r,w,}mb() fences on the
kernel-side. By updating the rings for load-acquire/store-release
semantics, the full barrier on the consumer side can be replaced with
improved performance as a nice side-effect.
Note that this change does *not* require similar changes on the
libbpf/userland side, however it is recommended [1].
On x86-64 systems, by removing the smp_mb() on the Rx and Tx side, the
l2fwd AF_XDP xdpsock sample performance increases by
1%. Weakly-ordered platforms, such as ARM64 might benefit even more.
[1] https://lore.kernel.org/bpf/20200316184423.GA14143@willie-the-truck/
Signed-off-by: Björn Töpel <redacted>
---
net/xdp/xsk_queue.h | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
@@ -47,19 +47,18 @@ struct xsk_queue {u64queue_empty_descs;};-/* The structure of the shared state of the rings are the same as the-*ringbufferinkernel/events/ring_buffer.c.FortheRxandcompletion-*ring,thekernelistheproduceranduserspaceistheconsumer.For-*theTxandfillrings,thekernelistheconsumeranduserspaceis-*theproducer.+/* The structure of the shared state of the rings are a simple+*circularbuffer,asoutlinedin+*Documentation/core-api/circular-buffers.rst.FortheRxand+*completionring,thekernelistheproduceranduserspaceisthe+*consumer.FortheTxandfillrings,thekernelistheconsumerand+*userspaceistheproducer.**producerconsumer*-*if(LOAD->consumer){LOAD->producer-*(A)smp_rmb()(C)+*if(LOAD->consumer){(A)LOAD.acq->producer(C)
Why is LOAD.acq not needed on the consumer side?
You mean why LOAD.acq is not needed on the *producer* side, i.e. the
->consumer?
Yes, of course! The two words were, like, right next to each other ;)
quoted
The ->consumer is a control dependency for the store, so there is no
ordering constraint for ->consumer at producer side. If there's no
space, no data is written. So, no barrier is needed there -- at least
that has been my perspective.
This is very similar to the buffer in
Documentation/core-api/circular-buffers.rst. Roping in Paul for some
guidance.
Yeah, I did read that, but got thrown off by this bit: "Therefore, the
unlock-lock pair between consecutive invocations of the consumer
provides the necessary ordering between the read of the index indicating
that the consumer has vacated a given element and the write by the
producer to that same element."
Since there is no lock in the XSK, what provides that guarantee here?
Oh, and BTW, when I re-read the rest of the comment in xsk_queue.h
(below the diagram you are changing in this patch), the text still talks
about "memory barriers" - maybe that should be updated to
release/acquire as well while you're changing things?
Make sense! I'll make sure to do that for the V2!
Björn
From: Björn Töpel <hidden> Date: 2021-03-03 22:56:51
On Wed, 3 Mar 2021 at 08:14, Björn Töpel [off-list ref] wrote:
On 2021-03-03 05:38, Andrii Nakryiko wrote:
quoted
On Mon, Mar 1, 2021 at 2:43 AM Björn Töpel [off-list ref] wrote:
quoted
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
Signed-off-by: Björn Töpel <redacted>
---
tools/lib/bpf/libbpf_util.h | 72 +++++++++++++++++++++++++------------
tools/lib/bpf/xsk.h | 17 +++------
2 files changed, 55 insertions(+), 34 deletions(-)
So, technically, these four are part of libbpf's API, as libbpf_util.h
is actually installed on target hosts. Seems like xsk.h is the only
one that is using them, though.
So the question is whether it's ok to remove them now?
I would say that. Ideally, the barriers shouldn't be visible at all,
since they're only used as an implementation detail for the static
inline functions.
quoted
And also, why wasn't this part of xsk.h in the first place?
I guess there was a "maybe it can be useful for more than the XDP socket
parts of libbpf"-idea. I'll move them to xsk.h for the v2, which will
make the migration easier.
Clarification! The reason for not having them in xsk.h, was that the
idea was that only the APIs allowed from the application should reside
there. IOW, libbpf_utils.h is only "implementation details". Again,
the static-inline function messes things up. Maybe moving to an
LTO-only world would be better, so we can get rid of the inlining all
together.
From: Björn Töpel <hidden> Date: 2021-03-03 22:56:51
On Tue, 2 Mar 2021 at 10:25, Daniel Borkmann [off-list ref] wrote:
[...]
quoted
I wonder if it's possible to cook a LKMM litmus test for this...?
That would be amazing! :-)
With the help of Paul and Alan [1] (Thanks!) I've cooked 8 litmus
tests for this [2].
The litmus tests is based on a one entry ring-buffer, and there are
two scenarios. The ring is full, i.e. the producer has written an
entry, so the consumer has to go first. The ring is empty, i.e. the
producer has to go first. There is one test for each permutation:
barrier only, acqrel only, acqrel+barrier, barrier+acqrel.
According to these tests the code in this series is correct. Now, for
the v2 some more wording/explanations are needed. Do you think I
should include the litmus tests in the patch, or just refer to them?
Paste parts of them into the cover?
(Another option which can be done independently could be to update [0] with outlining a
pairing scenario as we have here describing the forward/backward compatibility on the
barriers used, I think that would be quite useful as well.)
[0] Documentation/memory-barriers.txt
Yeah, I agree. There is some information on it though in the "SMP
BARRIER PAIRING" section:
--8<--
General barriers pair with each other, though they also pair with most
other types of barriers, albeit without multicopy atomicity. An acquire
barrier pairs with a release barrier, but both may also pair with other
barriers, including of course general barriers. A write barrier pairs
with a data dependency barrier, a control dependency, an acquire barrier,
a release barrier, a read barrier, or a general barrier. Similarly a
read barrier, control dependency, or a data dependency barrier pairs
with a write barrier, an acquire barrier, a release barrier, or a
general barrier:
-->8--
And there's the tools/memory-model/Documentation/cheatsheet.txt.
That being said; In this case more is more. :-D
Björn
[1] https://lore.kernel.org/lkml/CAJ+HfNhxWFeKnn1aZw-YJmzpBuCaoeGkXXKn058GhY-6ZBDtZA@mail.gmail.com/
[2] https://github.com/bjoto/litmus-xsk/commit/0db0dc426a7e1248f83e21f10f9e840f970f4cb7
quoted
quoted
Would also be great to get Will's ACK on that when you have a v2. :)
From: Will Deacon <will@kernel.org> Date: 2021-03-03 22:56:53
On Tue, Mar 02, 2021 at 10:13:21AM +0100, Daniel Borkmann wrote:
On 3/2/21 9:05 AM, Björn Töpel wrote:
quoted
On 2021-03-01 17:10, Toke Høiland-Jørgensen wrote:
quoted
Björn Töpel [off-list ref] writes:
quoted
From: Björn Töpel <redacted>
Now that the AF_XDP rings have load-acquire/store-release semantics,
move libbpf to that as well.
The library-internal libbpf_smp_{load_acquire,store_release} are only
valid for 32-bit words on ARM64.
Also, remove the barriers that are no longer in use.
So what happens if an updated libbpf is paired with an older kernel (or
vice versa)?
"This is fine." ;-) This was briefly discussed in [1], outlined by the
previous commit!
...even on POWER.
Could you put a summary or quote of that discussion on 'why it is okay and does not
cause /forward or backward/ compat issues with user space' directly into patch 1's
commit message?
I feel just referring to a link is probably less suitable in this case as it should
rather be part of the commit message that contains the justification on why it is
waterproof - at least it feels that specific area may be a bit under-documented, so
having it as direct part certainly doesn't hurt.
Would also be great to get Will's ACK on that when you have a v2. :)
Please stick me on CC for that and I'll take a look as I've forgotten pretty
much everything about this since last time :)
Will