History

Merge tag 'for-6.15/io_uring-rx-zc-20250325' of git://git.kernel.dk/linux

Pull io_uring zero-copy receive support from Jens Axboe: "This adds support for zero-copy receive with io_uring, enabling fast bulk receive of data directly into application memory, rather than needing to copy the data out of kernel memory. While this version only supports host memory as that was the initial target, other memory types are planned as well, with notably GPU memory coming next. This work depends on some networking components which were queued up on the networking side, but have now landed in your tree. This is the work of Pavel Begunkov and David Wei. From the v14 posting: 'We configure a page pool that a driver uses to fill a hw rx queue to hand out user pages instead of kernel pages. Any data that ends up hitting this hw rx queue will thus be dma'd into userspace memory directly, without needing to be bounced through kernel memory. 'Reading' data out of a socket instead becomes a _notification_ mechanism, where the kernel tells userspace where the data is. The overall approach is similar to the devmem TCP proposal This relies on hw header/data split, flow steering and RSS to ensure packet headers remain in kernel memory and only desired flows hit a hw rx queue configured for zero copy. Configuring this is outside of the scope of this patchset. We share netdev core infra with devmem TCP. The main difference is that io_uring is used for the uAPI and the lifetime of all objects are bound to an io_uring instance. Data is 'read' using a new io_uring request type. When done, data is returned via a new shared refill queue. A zero copy page pool refills a hw rx queue from this refill queue directly. Of course, the lifetime of these data buffers are managed by io_uring rather than the networking stack, with different refcounting rules. This patchset is the first step adding basic zero copy support. We will extend this iteratively with new features e.g. dynamically allocated zero copy areas, THP support, dmabuf support, improved copy fallback, general optimisations and more' In a local setup, I was able to saturate a 200G link with a single CPU core, and at netdev conf 0x19 earlier this month, Jamal reported 188Gbit of bandwidth using a single core (no HT, including soft-irq). Safe to say the efficiency is there, as bigger links would be needed to find the per-core limit, and it's considerably more efficient and faster than the existing devmem solution" * tag 'for-6.15/io_uring-rx-zc-20250325' of git://git.kernel.dk/linux: io_uring/zcrx: add selftest case for recvzc with read limit io_uring/zcrx: add a read limit to recvzc requests io_uring: add missing IORING_MAP_OFF_ZCRX_REGION in io_uring_mmap io_uring: Rename KConfig to Kconfig io_uring/zcrx: fix leaks on failed registration io_uring/zcrx: recheck ifq on shutdown io_uring/zcrx: add selftest net: add documentation for io_uring zcrx io_uring/zcrx: add copy fallback io_uring/zcrx: throttle receive requests io_uring/zcrx: set pp memory provider for an rx queue io_uring/zcrx: add io_recvzc request io_uring/zcrx: dma-map area for the device io_uring/zcrx: implement zerocopy receive pp memory provider io_uring/zcrx: grab a net device io_uring/zcrx: add io_zcrx_area io_uring/zcrx: add interface queue and refill queue

Linus Torvalds committed 1 year ago

Commit ca0b04b2 parents 15cb9a2 89baa2222 files · +1988 −2Browse files

Showing the changes to include/uapi/linux (1 of 22 files). Show all

Unified · Split

include/uapi/linux/io_uring.h+53−1
@@ -87,6 +87,7 @@ struct io_uring_sqe { · 86 unmodified lines
87 union {87 union {
88 __s32 splice_fd_in;88 __s32 splice_fd_in;
89 __u32 file_index;89 __u32 file_index;
90 __u32 zcrx_ifq_idx;
90 __u32 optlen;91 __u32 optlen;
91 struct {92 struct {
92 __u16 addr_len;93 __u16 addr_len;
@@ -278,6 +279,7 @@ enum io_uring_op { · 185 unmodified lines
278 IORING_OP_FTRUNCATE,279 IORING_OP_FTRUNCATE,
279 IORING_OP_BIND,280 IORING_OP_BIND,
280 IORING_OP_LISTEN,281 IORING_OP_LISTEN,
282 IORING_OP_RECV_ZC,
281 283
282 /* this goes last, obviously */284 /* this goes last, obviously */
283 IORING_OP_LAST,285 IORING_OP_LAST,
@@ -641,7 +643,8 @@ enum io_uring_register_op { · 357 unmodified lines
641 /* send MSG_RING without having a ring */643 /* send MSG_RING without having a ring */
642 IORING_REGISTER_SEND_MSG_RING = 31,644 IORING_REGISTER_SEND_MSG_RING = 31,
643 645
644 /* 32 reserved for zc rx */646 /* register a netdev hw rx queue for zerocopy */
647 IORING_REGISTER_ZCRX_IFQ = 32,
645 648
646 /* resize CQ ring */649 /* resize CQ ring */
647 IORING_REGISTER_RESIZE_RINGS = 33,650 IORING_REGISTER_RESIZE_RINGS = 33,
@@ -958,6 +961,55 @@ enum io_uring_socket_op { · 310 unmodified lines
958 SOCKET_URING_OP_SETSOCKOPT,961 SOCKET_URING_OP_SETSOCKOPT,
959};962};
960 963
964/* Zero copy receive refill queue entry */
965struct io_uring_zcrx_rqe {
966 __u64 off;
967 __u32 len;
968 __u32 __pad;
969};
970
971struct io_uring_zcrx_cqe {
972 __u64 off;
973 __u64 __pad;
974};
975
976/* The bit from which area id is encoded into offsets */
977#define IORING_ZCRX_AREA_SHIFT 48
978#define IORING_ZCRX_AREA_MASK (~(((__u64)1 << IORING_ZCRX_AREA_SHIFT) - 1))
979
980struct io_uring_zcrx_offsets {
981 __u32 head;
982 __u32 tail;
983 __u32 rqes;
984 __u32 __resv2;
985 __u64 __resv[2];
986};
987
988struct io_uring_zcrx_area_reg {
989 __u64 addr;
990 __u64 len;
991 __u64 rq_area_token;
992 __u32 flags;
993 __u32 __resv1;
994 __u64 __resv2[2];
995};
996
997/*
998 * Argument for IORING_REGISTER_ZCRX_IFQ
999 */
1000struct io_uring_zcrx_ifq_reg {
1001 __u32 if_idx;
1002 __u32 if_rxq;
1003 __u32 rq_entries;
1004 __u32 flags;
1005
1006 __u64 area_ptr; /* pointer to struct io_uring_zcrx_area_reg */
1007 __u64 region_ptr; /* struct io_uring_region_desc * */
1008
1009 struct io_uring_zcrx_offsets offsets;
1010 __u64 __resv[4];
1011};
1012
961#ifdef __cplusplus1013#ifdef __cplusplus
962}1014}
963#endif1015#endif