Skip to content

Commit 8f0b3cc

Browse files
minakuba-moo
authored andcommitted
tcp: RX path for devmem TCP
In tcp_recvmsg_locked(), detect if the skb being received by the user is a devmem skb. In this case - if the user provided the MSG_SOCK_DEVMEM flag - pass it to tcp_recvmsg_devmem() for custom handling. tcp_recvmsg_devmem() copies any data in the skb header to the linear buffer, and returns a cmsg to the user indicating the number of bytes returned in the linear buffer. tcp_recvmsg_devmem() then loops over the unaccessible devmem skb frags, and returns to the user a cmsg_devmem indicating the location of the data in the dmabuf device memory. cmsg_devmem contains this information: 1. the offset into the dmabuf where the payload starts. 'frag_offset'. 2. the size of the frag. 'frag_size'. 3. an opaque token 'frag_token' to return to the kernel when the buffer is to be released. The pages awaiting freeing are stored in the newly added sk->sk_user_frags, and each page passed to userspace is get_page()'d. This reference is dropped once the userspace indicates that it is done reading this page. All pages are released when the socket is destroyed. Signed-off-by: Willem de Bruijn <[email protected]> Signed-off-by: Kaiyuan Zhang <[email protected]> Signed-off-by: Mina Almasry <[email protected]> Reviewed-by: Pavel Begunkov <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 65249fe commit 8f0b3cc

File tree

12 files changed

+333
-5
lines changed

12 files changed

+333
-5
lines changed

arch/alpha/include/uapi/asm/socket.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@
140140
#define SO_PASSPIDFD 76
141141
#define SO_PEERPIDFD 77
142142

143+
#define SO_DEVMEM_LINEAR 78
144+
#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR
145+
#define SO_DEVMEM_DMABUF 79
146+
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
147+
143148
#if !defined(__KERNEL__)
144149

145150
#if __BITS_PER_LONG == 64

arch/mips/include/uapi/asm/socket.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@
151151
#define SO_PASSPIDFD 76
152152
#define SO_PEERPIDFD 77
153153

154+
#define SO_DEVMEM_LINEAR 78
155+
#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR
156+
#define SO_DEVMEM_DMABUF 79
157+
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
158+
154159
#if !defined(__KERNEL__)
155160

156161
#if __BITS_PER_LONG == 64

arch/parisc/include/uapi/asm/socket.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@
132132
#define SO_PASSPIDFD 0x404A
133133
#define SO_PEERPIDFD 0x404B
134134

135+
#define SO_DEVMEM_LINEAR 78
136+
#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR
137+
#define SO_DEVMEM_DMABUF 79
138+
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
139+
135140
#if !defined(__KERNEL__)
136141

137142
#if __BITS_PER_LONG == 64

arch/sparc/include/uapi/asm/socket.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@
133133
#define SO_PASSPIDFD 0x0055
134134
#define SO_PEERPIDFD 0x0056
135135

136+
#define SO_DEVMEM_LINEAR 0x0057
137+
#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR
138+
#define SO_DEVMEM_DMABUF 0x0058
139+
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
140+
136141
#if !defined(__KERNEL__)
137142

138143

include/linux/socket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ struct ucred {
327327
* plain text and require encryption
328328
*/
329329

330+
#define MSG_SOCK_DEVMEM 0x2000000 /* Receive devmem skbs as cmsg */
330331
#define MSG_ZEROCOPY 0x4000000 /* Use user data in kernel path */
331332
#define MSG_SPLICE_PAGES 0x8000000 /* Splice the pages from the iterator in sendmsg() */
332333
#define MSG_FASTOPEN 0x20000000 /* Send data in TCP SYN */

include/net/sock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ struct sk_filter;
337337
* @sk_txtime_report_errors: set report errors mode for SO_TXTIME
338338
* @sk_txtime_unused: unused txtime flags
339339
* @ns_tracker: tracker for netns reference
340+
* @sk_user_frags: xarray of pages the user is holding a reference on.
340341
*/
341342
struct sock {
342343
/*
@@ -542,6 +543,7 @@ struct sock {
542543
#endif
543544
struct rcu_head sk_rcu;
544545
netns_tracker ns_tracker;
546+
struct xarray sk_user_frags;
545547
};
546548

547549
struct sock_bh_locked {

include/uapi/asm-generic/socket.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@
135135
#define SO_PASSPIDFD 76
136136
#define SO_PEERPIDFD 77
137137

138+
#define SO_DEVMEM_LINEAR 78
139+
#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR
140+
#define SO_DEVMEM_DMABUF 79
141+
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
142+
138143
#if !defined(__KERNEL__)
139144

140145
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))

include/uapi/linux/uio.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ struct iovec
2020
__kernel_size_t iov_len; /* Must be size_t (1003.1g) */
2121
};
2222

23+
struct dmabuf_cmsg {
24+
__u64 frag_offset; /* offset into the dmabuf where the frag starts.
25+
*/
26+
__u32 frag_size; /* size of the frag. */
27+
__u32 frag_token; /* token representing this frag for
28+
* DEVMEM_DONTNEED.
29+
*/
30+
__u32 dmabuf_id; /* dmabuf id this frag belongs to. */
31+
__u32 flags; /* Currently unused. Reserved for future
32+
* uses.
33+
*/
34+
};
35+
2336
/*
2437
* UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
2538
*/

net/core/devmem.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ net_iov_binding(const struct net_iov *niov)
9191
return net_iov_owner(niov)->binding;
9292
}
9393

94+
static inline unsigned long net_iov_virtual_addr(const struct net_iov *niov)
95+
{
96+
struct dmabuf_genpool_chunk_owner *owner = net_iov_owner(niov);
97+
98+
return owner->base_virtual +
99+
((unsigned long)net_iov_idx(niov) << PAGE_SHIFT);
100+
}
101+
102+
static inline u32 net_iov_binding_id(const struct net_iov *niov)
103+
{
104+
return net_iov_owner(niov)->binding->id;
105+
}
106+
94107
static inline void
95108
net_devmem_dmabuf_binding_get(struct net_devmem_dmabuf_binding *binding)
96109
{
@@ -153,6 +166,15 @@ static inline void net_devmem_free_dmabuf(struct net_iov *ppiov)
153166
{
154167
}
155168

169+
static inline unsigned long net_iov_virtual_addr(const struct net_iov *niov)
170+
{
171+
return 0;
172+
}
173+
174+
static inline u32 net_iov_binding_id(const struct net_iov *niov)
175+
{
176+
return 0;
177+
}
156178
#endif
157179

158180
#endif /* _NET_DEVMEM_H */

0 commit comments

Comments
 (0)