uringmachine 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +0 -3
  4. data/CHANGELOG.md +13 -0
  5. data/Gemfile +11 -0
  6. data/README.md +266 -112
  7. data/Rakefile +8 -0
  8. data/TODO.md +14 -21
  9. data/benchmark/common.rb +2 -0
  10. data/benchmark/openssl.rb +77 -0
  11. data/benchmark/openssl_socketpair.rb +112 -0
  12. data/benchmark/sqlite.rb +1 -1
  13. data/docs/design/buffer_pool.md +1 -1
  14. data/docs/wroclove.rb.md +52 -0
  15. data/ext/um/extconf.rb +15 -0
  16. data/ext/um/um.c +392 -358
  17. data/ext/um/um.h +48 -23
  18. data/ext/um/um_async_op.c +9 -8
  19. data/ext/um/um_async_op_class.c +34 -3
  20. data/ext/um/um_class.c +705 -19
  21. data/ext/um/um_const.c +31 -0
  22. data/ext/um/um_mutex_class.c +12 -0
  23. data/ext/um/um_op.c +15 -1
  24. data/ext/um/um_queue_class.c +16 -0
  25. data/ext/um/um_ssl.c +109 -0
  26. data/ext/um/um_stream.c +9 -8
  27. data/ext/um/um_sync.c +18 -11
  28. data/ext/um/um_utils.c +17 -8
  29. data/grant-2025/interim-report.md +1 -1
  30. data/grant-2025/journal.md +4 -4
  31. data/grant-2025/tasks.md +6 -4
  32. data/lib/uringmachine/dns_resolver.rb +38 -0
  33. data/lib/uringmachine/fiber_scheduler.rb +7 -5
  34. data/lib/uringmachine/version.rb +1 -1
  35. data/lib/uringmachine.rb +106 -6
  36. data/test/helper.rb +15 -0
  37. data/test/test_async_op.rb +3 -2
  38. data/test/test_fiber_scheduler.rb +41 -1
  39. data/test/test_ssl.rb +85 -0
  40. data/test/test_stream.rb +11 -0
  41. data/test/test_um.rb +445 -11
  42. data/uringmachine.gemspec +1 -7
  43. data/vendor/liburing/examples/send-zerocopy.c +43 -31
  44. data/vendor/liburing/examples/zcrx.c +260 -69
  45. data/vendor/liburing/liburing.spec +1 -1
  46. data/vendor/liburing/src/include/liburing/io_uring.h +12 -0
  47. data/vendor/liburing/src/include/liburing.h +3 -2
  48. data/vendor/liburing/src/liburing-ffi.map +4 -0
  49. data/vendor/liburing/src/liburing.map +4 -0
  50. data/vendor/liburing/src/queue.c +12 -0
  51. data/vendor/liburing/src/register.c +1 -0
  52. data/vendor/liburing/src/setup.c +15 -7
  53. data/vendor/liburing/test/Makefile +8 -4
  54. data/vendor/liburing/test/conn-unreach.c +1 -1
  55. data/vendor/liburing/test/epwait.c +32 -6
  56. data/vendor/liburing/test/io-wq-exit.c +131 -0
  57. data/vendor/liburing/test/iowait.c +1 -1
  58. data/vendor/liburing/test/min-timeout.c +3 -1
  59. data/vendor/liburing/test/open-close.c +39 -0
  60. data/vendor/liburing/test/poll-update-trigger.c +85 -0
  61. data/vendor/liburing/test/recvsend_bundle.c +14 -11
  62. data/vendor/liburing/test/sendzc-bug.c +146 -0
  63. data/vendor/liburing/test/sqe-mixed-nop.c +151 -7
  64. data/vendor/liburing/test/test.h +2 -0
  65. data/vendor/liburing/test/timestamp-bug.c +135 -0
  66. data/vendor/liburing/test/timestamp.c +5 -0
  67. data/vendor/liburing/test/vec-regbuf.c +136 -1
  68. metadata +38 -283
  69. data/vendor/libressl/.github/scripts/changelog.sh +0 -74
  70. data/vendor/libressl/.github/workflows/android.yml +0 -35
  71. data/vendor/libressl/.github/workflows/cifuzz.yml +0 -33
  72. data/vendor/libressl/.github/workflows/cmake-config.yml +0 -98
  73. data/vendor/libressl/.github/workflows/coverity.yml +0 -69
  74. data/vendor/libressl/.github/workflows/emscripten.yml +0 -71
  75. data/vendor/libressl/.github/workflows/fedora-rawhide.yml +0 -39
  76. data/vendor/libressl/.github/workflows/freebsd.yml +0 -71
  77. data/vendor/libressl/.github/workflows/linux.yml +0 -71
  78. data/vendor/libressl/.github/workflows/macos.yml +0 -37
  79. data/vendor/libressl/.github/workflows/release.yml +0 -81
  80. data/vendor/libressl/.github/workflows/rust-openssl.yml +0 -47
  81. data/vendor/libressl/.github/workflows/solaris.yml +0 -37
  82. data/vendor/libressl/.github/workflows/windows.yml +0 -70
  83. data/vendor/libressl/.gitignore +0 -333
  84. data/vendor/libressl/CMakeLists.txt +0 -581
  85. data/vendor/libressl/COPYING +0 -133
  86. data/vendor/libressl/ChangeLog +0 -3280
  87. data/vendor/libressl/FindLibreSSL.cmake +0 -232
  88. data/vendor/libressl/LibreSSLConfig.cmake.in +0 -36
  89. data/vendor/libressl/Makefile.am +0 -60
  90. data/vendor/libressl/Makefile.am.common +0 -20
  91. data/vendor/libressl/OPENBSD_BRANCH +0 -1
  92. data/vendor/libressl/README.md +0 -238
  93. data/vendor/libressl/README.mingw.md +0 -43
  94. data/vendor/libressl/apps/CMakeLists.txt +0 -18
  95. data/vendor/libressl/apps/Makefile.am +0 -5
  96. data/vendor/libressl/apps/nc/CMakeLists.txt +0 -67
  97. data/vendor/libressl/apps/nc/Makefile.am +0 -64
  98. data/vendor/libressl/apps/nc/compat/accept4.c +0 -17
  99. data/vendor/libressl/apps/nc/compat/readpassphrase.c +0 -205
  100. data/vendor/libressl/apps/nc/compat/socket.c +0 -29
  101. data/vendor/libressl/apps/nc/compat/sys/socket.h +0 -30
  102. data/vendor/libressl/apps/ocspcheck/CMakeLists.txt +0 -44
  103. data/vendor/libressl/apps/ocspcheck/Makefile.am +0 -45
  104. data/vendor/libressl/apps/ocspcheck/compat/.gitignore +0 -0
  105. data/vendor/libressl/apps/openssl/CMakeLists.txt +0 -97
  106. data/vendor/libressl/apps/openssl/Makefile.am +0 -108
  107. data/vendor/libressl/apps/openssl/apps_win.c +0 -138
  108. data/vendor/libressl/apps/openssl/certhash_win.c +0 -13
  109. data/vendor/libressl/apps/openssl/compat/clock_gettime_osx.c +0 -26
  110. data/vendor/libressl/apps/openssl/compat/poll_win.c +0 -329
  111. data/vendor/libressl/appveyor.yml +0 -53
  112. data/vendor/libressl/autogen.sh +0 -15
  113. data/vendor/libressl/check-release.sh +0 -86
  114. data/vendor/libressl/cmake_export_symbol.cmake +0 -71
  115. data/vendor/libressl/cmake_uninstall.cmake.in +0 -36
  116. data/vendor/libressl/config +0 -17
  117. data/vendor/libressl/configure.ac +0 -165
  118. data/vendor/libressl/crypto/CMakeLists.txt +0 -863
  119. data/vendor/libressl/crypto/Makefile.am +0 -962
  120. data/vendor/libressl/crypto/Makefile.am.arc4random +0 -46
  121. data/vendor/libressl/crypto/Makefile.am.elf-mips +0 -14
  122. data/vendor/libressl/crypto/Makefile.am.elf-mips64 +0 -14
  123. data/vendor/libressl/crypto/Makefile.am.elf-x86_64 +0 -35
  124. data/vendor/libressl/crypto/Makefile.am.macosx-x86_64 +0 -35
  125. data/vendor/libressl/crypto/Makefile.am.masm-x86_64 +0 -22
  126. data/vendor/libressl/crypto/Makefile.am.mingw64-x86_64 +0 -23
  127. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_darwin.c +0 -60
  128. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_linux.c +0 -62
  129. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_none.c +0 -26
  130. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_windows.c +0 -36
  131. data/vendor/libressl/crypto/arch/loongarch64/crypto_arch.h +0 -21
  132. data/vendor/libressl/crypto/arch/mips/crypto_arch.h +0 -21
  133. data/vendor/libressl/crypto/bn/arch/loongarch64/bn_arch.h +0 -23
  134. data/vendor/libressl/crypto/bn/arch/mips/bn_arch.h +0 -24
  135. data/vendor/libressl/crypto/compat/.gitignore +0 -31
  136. data/vendor/libressl/crypto/compat/arc4random.h +0 -41
  137. data/vendor/libressl/crypto/compat/b_win.c +0 -55
  138. data/vendor/libressl/crypto/compat/bsd-asprintf.c +0 -96
  139. data/vendor/libressl/crypto/compat/crypto_lock_win.c +0 -56
  140. data/vendor/libressl/crypto/compat/explicit_bzero_win.c +0 -13
  141. data/vendor/libressl/crypto/compat/freezero.c +0 -32
  142. data/vendor/libressl/crypto/compat/getdelim.c +0 -78
  143. data/vendor/libressl/crypto/compat/getline.c +0 -40
  144. data/vendor/libressl/crypto/compat/getopt_long.c +0 -528
  145. data/vendor/libressl/crypto/compat/getpagesize.c +0 -18
  146. data/vendor/libressl/crypto/compat/getprogname_linux.c +0 -23
  147. data/vendor/libressl/crypto/compat/getprogname_unimpl.c +0 -7
  148. data/vendor/libressl/crypto/compat/getprogname_windows.c +0 -13
  149. data/vendor/libressl/crypto/compat/posix_win.c +0 -296
  150. data/vendor/libressl/crypto/compat/syslog_r.c +0 -19
  151. data/vendor/libressl/crypto/compat/ui_openssl_win.c +0 -334
  152. data/vendor/libressl/dist.sh +0 -22
  153. data/vendor/libressl/gen-coverage-report.sh +0 -58
  154. data/vendor/libressl/gen-openbsd-tags.sh +0 -20
  155. data/vendor/libressl/include/CMakeLists.txt +0 -61
  156. data/vendor/libressl/include/Makefile.am +0 -79
  157. data/vendor/libressl/include/arch/loongarch64/opensslconf.h +0 -150
  158. data/vendor/libressl/include/arch/mips/opensslconf.h +0 -150
  159. data/vendor/libressl/include/compat/arpa/inet.h +0 -15
  160. data/vendor/libressl/include/compat/arpa/nameser.h +0 -25
  161. data/vendor/libressl/include/compat/cet.h +0 -19
  162. data/vendor/libressl/include/compat/dirent.h +0 -17
  163. data/vendor/libressl/include/compat/dirent_msvc.h +0 -611
  164. data/vendor/libressl/include/compat/endian.h +0 -161
  165. data/vendor/libressl/include/compat/err.h +0 -95
  166. data/vendor/libressl/include/compat/fcntl.h +0 -32
  167. data/vendor/libressl/include/compat/getopt.h +0 -50
  168. data/vendor/libressl/include/compat/limits.h +0 -25
  169. data/vendor/libressl/include/compat/netdb.h +0 -10
  170. data/vendor/libressl/include/compat/netinet/in.h +0 -19
  171. data/vendor/libressl/include/compat/netinet/ip.h +0 -49
  172. data/vendor/libressl/include/compat/netinet/tcp.h +0 -10
  173. data/vendor/libressl/include/compat/poll.h +0 -63
  174. data/vendor/libressl/include/compat/pthread.h +0 -122
  175. data/vendor/libressl/include/compat/readpassphrase.h +0 -44
  176. data/vendor/libressl/include/compat/resolv.h +0 -24
  177. data/vendor/libressl/include/compat/stdint.h +0 -31
  178. data/vendor/libressl/include/compat/stdio.h +0 -65
  179. data/vendor/libressl/include/compat/stdlib.h +0 -57
  180. data/vendor/libressl/include/compat/string.h +0 -98
  181. data/vendor/libressl/include/compat/sys/_null.h +0 -18
  182. data/vendor/libressl/include/compat/sys/ioctl.h +0 -11
  183. data/vendor/libressl/include/compat/sys/mman.h +0 -19
  184. data/vendor/libressl/include/compat/sys/param.h +0 -15
  185. data/vendor/libressl/include/compat/sys/queue.h +0 -536
  186. data/vendor/libressl/include/compat/sys/select.h +0 -10
  187. data/vendor/libressl/include/compat/sys/socket.h +0 -18
  188. data/vendor/libressl/include/compat/sys/stat.h +0 -129
  189. data/vendor/libressl/include/compat/sys/time.h +0 -37
  190. data/vendor/libressl/include/compat/sys/tree.h +0 -1006
  191. data/vendor/libressl/include/compat/sys/types.h +0 -69
  192. data/vendor/libressl/include/compat/sys/uio.h +0 -17
  193. data/vendor/libressl/include/compat/syslog.h +0 -38
  194. data/vendor/libressl/include/compat/time.h +0 -59
  195. data/vendor/libressl/include/compat/unistd.h +0 -83
  196. data/vendor/libressl/include/compat/win32netcompat.h +0 -57
  197. data/vendor/libressl/include/openssl/Makefile.am.tpl +0 -45
  198. data/vendor/libressl/libcrypto.pc.in +0 -28
  199. data/vendor/libressl/libressl.pub +0 -2
  200. data/vendor/libressl/libssl.pc.in +0 -28
  201. data/vendor/libressl/libtls.pc.in +0 -28
  202. data/vendor/libressl/m4/ax_add_fortify_source.m4 +0 -80
  203. data/vendor/libressl/m4/ax_check_compile_flag.m4 +0 -53
  204. data/vendor/libressl/m4/check-hardening-options.m4 +0 -110
  205. data/vendor/libressl/m4/check-libc.m4 +0 -189
  206. data/vendor/libressl/m4/check-os-options.m4 +0 -181
  207. data/vendor/libressl/m4/disable-compiler-warnings.m4 +0 -44
  208. data/vendor/libressl/man/CMakeLists.txt +0 -26
  209. data/vendor/libressl/man/links +0 -2780
  210. data/vendor/libressl/man/update_links.sh +0 -25
  211. data/vendor/libressl/openssl.pc.in +0 -11
  212. data/vendor/libressl/patches/bn_shift.patch +0 -34
  213. data/vendor/libressl/patches/crypto_arch.h.patch +0 -34
  214. data/vendor/libressl/patches/crypto_namespace.h.patch +0 -22
  215. data/vendor/libressl/patches/netcat.c.patch +0 -178
  216. data/vendor/libressl/patches/openssl.c.patch +0 -12
  217. data/vendor/libressl/patches/opensslfeatures.h.patch +0 -49
  218. data/vendor/libressl/patches/patch-amd64-crypto-cpu-caps.c.patch +0 -20
  219. data/vendor/libressl/patches/patch-i386-crypto-cpu-caps.c.patch +0 -20
  220. data/vendor/libressl/patches/speed.c.patch +0 -114
  221. data/vendor/libressl/patches/ssl_namespace.h.patch +0 -21
  222. data/vendor/libressl/patches/tls.h.patch +0 -16
  223. data/vendor/libressl/patches/tls_config.c.patch +0 -15
  224. data/vendor/libressl/patches/win32_amd64_bn_arch.h.patch +0 -28
  225. data/vendor/libressl/patches/windows_headers.patch +0 -80
  226. data/vendor/libressl/scripts/config.guess +0 -1774
  227. data/vendor/libressl/scripts/config.sub +0 -1907
  228. data/vendor/libressl/scripts/i686-w64-mingw32.cmake +0 -9
  229. data/vendor/libressl/scripts/test +0 -210
  230. data/vendor/libressl/scripts/wrap-compiler-for-flag-check +0 -31
  231. data/vendor/libressl/scripts/x86_64-w64-mingw32.cmake +0 -9
  232. data/vendor/libressl/ssl/CMakeLists.txt +0 -183
  233. data/vendor/libressl/ssl/Makefile.am +0 -187
  234. data/vendor/libressl/tests/CMakeLists.txt +0 -970
  235. data/vendor/libressl/tests/Makefile.am +0 -944
  236. data/vendor/libressl/tests/aeadtest.sh +0 -30
  237. data/vendor/libressl/tests/arc4randomforktest.sh +0 -21
  238. data/vendor/libressl/tests/asn1time_small.test +0 -10
  239. data/vendor/libressl/tests/cmake/CMakeLists.txt +0 -52
  240. data/vendor/libressl/tests/cmake/crypto.c +0 -7
  241. data/vendor/libressl/tests/cmake/ssl.c +0 -6
  242. data/vendor/libressl/tests/cmake/tls.c +0 -6
  243. data/vendor/libressl/tests/compat/pipe2.c +0 -186
  244. data/vendor/libressl/tests/dtlstest.sh +0 -28
  245. data/vendor/libressl/tests/evptest.sh +0 -22
  246. data/vendor/libressl/tests/keypairtest.sh +0 -27
  247. data/vendor/libressl/tests/mlkem_tests.sh +0 -39
  248. data/vendor/libressl/tests/ocsptest.bat +0 -25
  249. data/vendor/libressl/tests/ocsptest.sh +0 -23
  250. data/vendor/libressl/tests/openssl.cnf +0 -29
  251. data/vendor/libressl/tests/optionstest.c +0 -381
  252. data/vendor/libressl/tests/pidwraptest.c +0 -85
  253. data/vendor/libressl/tests/pidwraptest.sh +0 -26
  254. data/vendor/libressl/tests/quictest.bat +0 -27
  255. data/vendor/libressl/tests/quictest.sh +0 -30
  256. data/vendor/libressl/tests/renegotiation_test.bat +0 -27
  257. data/vendor/libressl/tests/renegotiation_test.sh +0 -30
  258. data/vendor/libressl/tests/rfc5280time_small.test +0 -10
  259. data/vendor/libressl/tests/servertest.bat +0 -27
  260. data/vendor/libressl/tests/servertest.sh +0 -30
  261. data/vendor/libressl/tests/shutdowntest.bat +0 -27
  262. data/vendor/libressl/tests/shutdowntest.sh +0 -30
  263. data/vendor/libressl/tests/ssltest.bat +0 -32
  264. data/vendor/libressl/tests/ssltest.sh +0 -48
  265. data/vendor/libressl/tests/testdsa.bat +0 -47
  266. data/vendor/libressl/tests/testdsa.sh +0 -57
  267. data/vendor/libressl/tests/testenc.bat +0 -85
  268. data/vendor/libressl/tests/testenc.sh +0 -93
  269. data/vendor/libressl/tests/testrsa.bat +0 -47
  270. data/vendor/libressl/tests/testrsa.sh +0 -57
  271. data/vendor/libressl/tests/testssl.bat +0 -171
  272. data/vendor/libressl/tests/tlstest.bat +0 -27
  273. data/vendor/libressl/tests/tlstest.sh +0 -28
  274. data/vendor/libressl/tls/CMakeLists.txt +0 -125
  275. data/vendor/libressl/tls/Makefile.am +0 -76
  276. data/vendor/libressl/tls/compat/ftruncate.c +0 -17
  277. data/vendor/libressl/tls/compat/pread.c +0 -29
  278. data/vendor/libressl/tls/compat/pwrite.c +0 -29
  279. data/vendor/libressl/update.sh +0 -460
data/uringmachine.gemspec CHANGED
@@ -15,14 +15,8 @@ Gem::Specification.new do |s|
15
15
  "changelog_uri" => "https://github.com/digital-fabric/uringmachine/blob/master/CHANGELOG.md"
16
16
  }
17
17
  s.rdoc_options = ["--title", "UringMachine", "--main", "README.md"]
18
- s.extra_rdoc_files = ["README.md"]
18
+ s.extra_rdoc_files = `git ls-files -z *.rdoc *.md lib/*.rb lib/**/*.rb ext/um/*.c ext/um/*.h benchmark/*.md benchmark/*.png`.split("\x0")
19
19
  s.extensions = ["ext/um/extconf.rb"]
20
20
  s.require_paths = ["lib"]
21
21
  s.required_ruby_version = '>= 3.5'
22
-
23
- s.add_development_dependency 'rake-compiler', '~>1.3.0'
24
- s.add_development_dependency 'minitest', '~>5.26.2'
25
- s.add_development_dependency 'benchmark'
26
- s.add_development_dependency 'benchmark-ips'
27
- s.add_development_dependency 'http_parser.rb', '~>0.8.0'
28
22
  end
@@ -60,6 +60,9 @@ struct thread_data {
60
60
  int fd;
61
61
  };
62
62
 
63
+ static int page_size;
64
+ static size_t alloc_size;
65
+
63
66
  static bool cfg_reg_ringfd = true;
64
67
  static bool cfg_fixed_files = 1;
65
68
  static bool cfg_zc = 1;
@@ -83,7 +86,6 @@ static bool cfg_verify;
83
86
  static socklen_t cfg_alen;
84
87
  static char *str_addr = NULL;
85
88
 
86
- static char payload_buf[IP_MAXPACKET + PATTERN_SIZE] __attribute__((aligned(4096)));
87
89
  static char *payload;
88
90
  static struct thread_data threads[MAX_THREADS];
89
91
  static pthread_barrier_t barrier;
@@ -521,7 +523,7 @@ static void usage(const char *filepath)
521
523
  static void parse_opts(int argc, char **argv)
522
524
  {
523
525
  const char *cfg_test;
524
- const int max_payload_len = IP_MAXPACKET -
526
+ const int max_udp_payload_len = IP_MAXPACKET -
525
527
  sizeof(struct ipv6hdr) -
526
528
  sizeof(struct tcphdr) -
527
529
  40 /* max tcp options */;
@@ -533,7 +535,7 @@ static void parse_opts(int argc, char **argv)
533
535
  exit(0);
534
536
  }
535
537
 
536
- cfg_payload_len = max_payload_len;
538
+ cfg_payload_len = max_udp_payload_len;
537
539
 
538
540
  while ((c = getopt(argc, argv, "46D:p:s:t:n:z:I:b:l:dC:T:Ryv")) != -1) {
539
541
  switch (c) {
@@ -607,21 +609,25 @@ static void parse_opts(int argc, char **argv)
607
609
  else
608
610
  t_error(1, 0, "unknown cfg_test %s", cfg_test);
609
611
 
610
- if (cfg_nr_reqs > MAX_SUBMIT_NR)
611
- t_error(1, 0, "-n: submit batch nr exceeds max (%d)", MAX_SUBMIT_NR);
612
- if (cfg_payload_len > max_payload_len)
613
- t_error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);
614
- if (!cfg_nr_reqs)
615
- t_error(1, 0, "-n: submit batch can't be zero");
616
- if (cfg_ifname && cfg_rx)
617
- t_error(1, 0, "Interface can only be specified for tx");
618
- if (cfg_nr_reqs > 1 && cfg_type == SOCK_STREAM) {
619
- printf("warning: submit batching >1 with TCP sockets will cause data reordering");
612
+ if (!cfg_rx) {
613
+ if (cfg_nr_reqs > MAX_SUBMIT_NR)
614
+ t_error(1, 0, "-n: submit batch nr exceeds max (%d)", MAX_SUBMIT_NR);
615
+ if (!cfg_nr_reqs)
616
+ t_error(1, 0, "-n: submit batch can't be zero");
617
+ if (cfg_nr_reqs > 1 && cfg_type == SOCK_STREAM) {
618
+ printf("warning: submit batching >1 with TCP sockets will cause data reordering");
619
+ if (cfg_verify)
620
+ t_error(1, 0, "can't verify data because of reordering");
621
+ }
622
+ } else {
623
+ if (cfg_ifname)
624
+ t_error(1, 0, "Interface can only be specified for tx");
620
625
  if (cfg_verify)
621
- t_error(1, 0, "can't verify data because of reordering");
626
+ t_error(1, 0, "Server mode doesn't support data verification");
622
627
  }
623
- if (cfg_rx && cfg_verify)
624
- t_error(1, 0, "Server mode doesn't support data verification");
628
+
629
+ if (cfg_type == SOCK_DGRAM && cfg_payload_len > max_udp_payload_len)
630
+ t_error(1, 0, "-s: UDP payload exceeds max (%d)", max_udp_payload_len);
625
631
 
626
632
  str_addr = daddr;
627
633
 
@@ -631,28 +637,25 @@ static void parse_opts(int argc, char **argv)
631
637
 
632
638
  static void init_buffers(void)
633
639
  {
634
- size_t size;
640
+ unsigned map_flags = MAP_PRIVATE | MAP_ANONYMOUS;
635
641
  int i;
636
642
 
637
- payload = payload_buf;
638
- size = sizeof(payload_buf);
643
+ alloc_size = cfg_payload_len + PATTERN_SIZE;
644
+ alloc_size = (alloc_size + page_size - 1) / page_size * page_size;
639
645
 
640
646
  if (cfg_hugetlb) {
641
- size = 1 << 21;
642
- payload = mmap(NULL, size, PROT_READ | PROT_WRITE,
643
- MAP_PRIVATE | MAP_HUGETLB | MAP_HUGE_2MB | MAP_ANONYMOUS,
644
- -1, 0);
645
- if (payload == MAP_FAILED)
646
- t_error(0, 1, "huge pages alloc failed");
647
+ size_t huge_size = 1 << 21;
648
+
649
+ alloc_size = (alloc_size + huge_size - 1) / huge_size * huge_size;
650
+ map_flags |= MAP_HUGETLB | MAP_HUGE_2MB;
647
651
  }
648
652
 
649
- if (cfg_payload_len + PATTERN_SIZE > size)
650
- t_error(1, 0, "Buffers are too small");
653
+ payload = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, map_flags, -1, 0);
654
+ if (payload == MAP_FAILED)
655
+ t_error(0, 1, "buffer alloc failed (size %zu)\n", alloc_size);
651
656
 
652
- if (cfg_verify) {
653
- for (i = 0; i < size; i++)
654
- payload[i] = 'a' + (i % PATTERN_SIZE);
655
- }
657
+ for (i = 0; i < alloc_size; i++)
658
+ payload[i] = 'a' + (i % PATTERN_SIZE);
656
659
  }
657
660
 
658
661
  int main(int argc, char **argv)
@@ -663,6 +666,12 @@ int main(int argc, char **argv)
663
666
  unsigned int i;
664
667
  void *res;
665
668
 
669
+ page_size = sysconf(_SC_PAGESIZE);
670
+ if (page_size < 0) {
671
+ perror("sysconf(_SC_PAGESIZE)");
672
+ return 1;
673
+ }
674
+
666
675
  parse_opts(argc, argv);
667
676
  init_buffers();
668
677
  set_cpu_affinity();
@@ -700,6 +709,9 @@ int main(int argc, char **argv)
700
709
  packets * 1000 / tsum,
701
710
  (bytes >> 20) * 1000 / tsum);
702
711
  }
712
+
713
+ if (payload)
714
+ munmap(payload, alloc_size);
703
715
  pthread_barrier_destroy(&barrier);
704
716
  return 0;
705
717
  }
@@ -44,6 +44,14 @@
44
44
  #include "liburing.h"
45
45
  #include "helpers.h"
46
46
 
47
+ enum {
48
+ AFFINITY_MODE_NONE,
49
+ AFFINITY_MODE_SAME,
50
+ AFFINITY_MODE_DIFFERENT,
51
+
52
+ __AFFINITY_MODE_MAX,
53
+ };
54
+
47
55
  enum {
48
56
  RQ_ALLOC_USER,
49
57
  RQ_ALLOC_KERNEL,
@@ -51,9 +59,6 @@ enum {
51
59
  __RQ_ALLOC_MAX,
52
60
  };
53
61
 
54
- static long page_size;
55
- #define AREA_SIZE (8192 * page_size)
56
-
57
62
  #define REQ_TYPE_SHIFT 3
58
63
  #define REQ_TYPE_MASK ((1UL << REQ_TYPE_SHIFT) - 1)
59
64
 
@@ -69,28 +74,92 @@ enum {
69
74
  REQ_TYPE_RX = 2,
70
75
  };
71
76
 
77
+ struct zc_conn {
78
+ int sockfd;
79
+ unsigned long received;
80
+ unsigned stat_nr_reqs;
81
+ unsigned stat_nr_cqes;
82
+ };
83
+
84
+ static unsigned cfg_rq_entries = 8192;
85
+ static unsigned cfg_cq_entries = 8192;
86
+ static long cfg_area_size = 256 * 1024 * 1024;
72
87
  static int cfg_port = 8000;
73
88
  static const char *cfg_ifname;
74
89
  static int cfg_queue_id = -1;
75
90
  static bool cfg_verify_data = false;
76
91
  static size_t cfg_size = 0;
92
+ static unsigned cfg_affinity_mode = AFFINITY_MODE_NONE;
77
93
  static unsigned cfg_rq_alloc_mode = RQ_ALLOC_USER;
78
94
  static unsigned cfg_area_type = AREA_TYPE_NORMAL;
79
95
  static struct sockaddr_in6 cfg_addr;
80
96
 
97
+ static long page_size;
98
+
81
99
  static void *area_ptr;
82
100
  static void *ring_ptr;
83
101
  static size_t ring_size;
84
102
  static struct io_uring_zcrx_rq rq_ring;
85
103
  static unsigned long area_token;
86
- static int connfd;
87
104
  static bool stop;
88
- static size_t received;
89
105
  static __u32 zcrx_id;
90
106
 
91
107
  static int dmabuf_fd;
92
108
  static int memfd;
93
109
 
110
+ static int listen_fd;
111
+ static int target_cpu = -1;
112
+
113
+ static int get_sock_cpu(int sockfd)
114
+ {
115
+ int cpu;
116
+ socklen_t len = sizeof(cpu);
117
+
118
+ if (getsockopt(sockfd, SOL_SOCKET, SO_INCOMING_CPU, &cpu, &len))
119
+ t_error(1, errno, "getsockopt failed\n");
120
+ return cpu;
121
+ }
122
+
123
+ static void set_affinity(int sockfd)
124
+ {
125
+ int new_cpu = -1;
126
+ int sock_cpu;
127
+ cpu_set_t mask;
128
+
129
+ if (cfg_affinity_mode == AFFINITY_MODE_NONE)
130
+ return;
131
+
132
+ sock_cpu = get_sock_cpu(sockfd);
133
+ if (sock_cpu == -1)
134
+ t_error(1, 0, "Can't socket's CPU");
135
+
136
+ if (cfg_affinity_mode == AFFINITY_MODE_SAME) {
137
+ new_cpu = sock_cpu;
138
+ } else if (cfg_affinity_mode == AFFINITY_MODE_DIFFERENT) {
139
+ if (target_cpu != -1 && target_cpu != sock_cpu)
140
+ new_cpu = target_cpu;
141
+ else
142
+ new_cpu = sock_cpu ^ 1;
143
+ }
144
+
145
+ if (target_cpu != -1 && new_cpu != target_cpu) {
146
+ printf("Couldn't set affinity for multi socket setup\n");
147
+ return;
148
+ }
149
+
150
+ CPU_ZERO(&mask);
151
+ CPU_SET(new_cpu, &mask);
152
+ if (sched_setaffinity(0, sizeof(mask), &mask))
153
+ t_error(1, errno, "sched_setaffinity() failed\n");
154
+ target_cpu = new_cpu;
155
+ }
156
+
157
+ static struct zc_conn *get_connection(__u64 user_data)
158
+ {
159
+ user_data &= ~REQ_TYPE_MASK;
160
+ return (struct zc_conn *)(unsigned long)user_data;
161
+ }
162
+
94
163
  static inline size_t get_refill_ring_size(unsigned int rq_entries)
95
164
  {
96
165
  ring_size = rq_entries * sizeof(struct io_uring_zcrx_rqe);
@@ -106,36 +175,36 @@ static void zcrx_populate_area_udmabuf(struct io_uring_zcrx_area_reg *area_reg)
106
175
 
107
176
  devfd = open("/dev/udmabuf", O_RDWR);
108
177
  if (devfd < 0)
109
- t_error(1, devfd, "Failed to open udmabuf dev");
178
+ t_error(1, errno, "Failed to open udmabuf dev");
110
179
 
111
180
  memfd = memfd_create("udmabuf-test", MFD_ALLOW_SEALING);
112
181
  if (memfd < 0)
113
- t_error(1, memfd, "Failed to open udmabuf dev");
182
+ t_error(1, errno, "Failed to open udmabuf dev");
114
183
 
115
184
  ret = fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK);
116
185
  if (ret < 0)
117
- t_error(1, 0, "Failed to set seals");
186
+ t_error(1, errno, "Failed to set seals");
118
187
 
119
- ret = ftruncate(memfd, AREA_SIZE);
188
+ ret = ftruncate(memfd, cfg_area_size);
120
189
  if (ret == -1)
121
- t_error(1, 0, "Failed to resize udmabuf");
190
+ t_error(1, errno, "Failed to resize udmabuf");
122
191
 
123
192
  memset(&create, 0, sizeof(create));
124
193
  create.memfd = memfd;
125
194
  create.offset = 0;
126
- create.size = AREA_SIZE;
195
+ create.size = cfg_area_size;
127
196
  dmabuf_fd = ioctl(devfd, UDMABUF_CREATE, &create);
128
197
  if (dmabuf_fd < 0)
129
- t_error(1, dmabuf_fd, "Failed to create udmabuf");
198
+ t_error(1, errno, "Failed to create udmabuf");
130
199
 
131
- area_ptr = mmap(NULL, AREA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
200
+ area_ptr = mmap(NULL, cfg_area_size, PROT_READ | PROT_WRITE, MAP_SHARED,
132
201
  dmabuf_fd, 0);
133
202
  if (area_ptr == MAP_FAILED)
134
- t_error(1, 0, "Failed to mmap udmabuf");
203
+ t_error(1, errno, "Failed to mmap udmabuf");
135
204
 
136
205
  memset(area_reg, 0, sizeof(*area_reg));
137
206
  area_reg->addr = 0; /* offset into dmabuf */
138
- area_reg->len = AREA_SIZE;
207
+ area_reg->len = cfg_area_size;
139
208
  area_reg->flags |= IORING_ZCRX_AREA_DMABUF;
140
209
  area_reg->dmabuf_fd = dmabuf_fd;
141
210
 
@@ -152,10 +221,10 @@ static void zcrx_populate_area(struct io_uring_zcrx_area_reg *area_reg)
152
221
  return;
153
222
  }
154
223
  if (cfg_area_type == AREA_TYPE_NORMAL) {
155
- area_ptr = mmap(NULL, AREA_SIZE, prot,
224
+ area_ptr = mmap(NULL, cfg_area_size, prot,
156
225
  flags, 0, 0);
157
226
  } else if (cfg_area_type == AREA_TYPE_HUGE_PAGES) {
158
- area_ptr = mmap(NULL, AREA_SIZE, prot,
227
+ area_ptr = mmap(NULL, cfg_area_size, prot,
159
228
  flags | MAP_HUGETLB | MAP_HUGE_2MB, -1, 0);
160
229
  }
161
230
 
@@ -164,7 +233,7 @@ static void zcrx_populate_area(struct io_uring_zcrx_area_reg *area_reg)
164
233
 
165
234
  memset(area_reg, 0, sizeof(*area_reg));
166
235
  area_reg->addr = uring_ptr_to_u64(area_ptr);
167
- area_reg->len = AREA_SIZE;
236
+ area_reg->len = cfg_area_size;
168
237
  area_reg->flags = 0;
169
238
  }
170
239
 
@@ -172,7 +241,7 @@ static void setup_zcrx(struct io_uring *ring)
172
241
  {
173
242
  struct io_uring_zcrx_area_reg area_reg;
174
243
  unsigned int ifindex;
175
- unsigned int rq_entries = 4096;
244
+ unsigned int rq_entries = cfg_rq_entries;
176
245
  unsigned rq_flags = 0;
177
246
  int ret;
178
247
 
@@ -239,59 +308,160 @@ static void add_accept(struct io_uring *ring, int sockfd)
239
308
  sqe->user_data = REQ_TYPE_ACCEPT;
240
309
  }
241
310
 
242
- static void add_recvzc(struct io_uring *ring, int sockfd, size_t len)
311
+ static void add_recvzc(struct io_uring *ring, struct zc_conn *conn, size_t len)
243
312
  {
244
313
  struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
314
+ __u64 token;
315
+
316
+ token = (__u64)(unsigned long)conn;
317
+ token |= REQ_TYPE_RX;
245
318
 
246
- io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, sockfd, NULL, len, 0);
319
+ conn->stat_nr_reqs++;
320
+ io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, conn->sockfd, NULL, len, 0);
247
321
  sqe->ioprio |= IORING_RECV_MULTISHOT;
248
322
  sqe->zcrx_ifq_idx = zcrx_id;
249
- sqe->user_data = REQ_TYPE_RX;
323
+ sqe->user_data = token;
324
+ }
325
+
326
+ static void print_socket_info(int sockfd)
327
+ {
328
+ struct sockaddr_in6 peer_addr;
329
+ socklen_t addr_len = sizeof(peer_addr);
330
+ char ip_str[INET6_ADDRSTRLEN];
331
+ int port;
332
+
333
+ if (getpeername(sockfd, (struct sockaddr *)&peer_addr, &addr_len) < 0) {
334
+ t_error(1, errno, "getpeername failed");
335
+ return;
336
+ }
337
+ if (!inet_ntop(AF_INET6, &peer_addr.sin6_addr, ip_str, sizeof(ip_str))) {
338
+ t_error(1, errno, "inet_ntop failed");
339
+ return;
340
+ }
341
+ port = ntohs(peer_addr.sin6_port);
342
+
343
+ printf("socket accepted: fd %i, Peer IP %s, Peer port %d\n",
344
+ sockfd, ip_str, port);
250
345
  }
251
346
 
252
347
  static void process_accept(struct io_uring *ring, struct io_uring_cqe *cqe)
253
348
  {
254
- if (cqe->res < 0)
255
- t_error(1, 0, "accept()");
256
- if (connfd)
349
+ struct zc_conn *conn;
350
+
351
+ if (cqe->res < 0) {
352
+ printf("Accept failed %i, terminate\n", cqe->res);
353
+ stop = false;
354
+ return;
355
+ }
356
+
357
+ conn = aligned_alloc(64, sizeof(*conn));
358
+ if (!conn)
359
+ t_error(1, 0, "can't allocate conn structure");
360
+ if (conn->sockfd)
257
361
  t_error(1, 0, "Unexpected second connection");
258
362
 
259
- connfd = cqe->res;
260
- add_recvzc(ring, connfd, cfg_size);
363
+ memset(conn, 0, sizeof(*conn));
364
+ conn->sockfd = cqe->res;
365
+ print_socket_info(conn->sockfd);
366
+ set_affinity(conn->sockfd);
367
+ add_recvzc(ring, conn, cfg_size);
368
+
369
+ add_accept(ring, listen_fd);
261
370
  }
262
371
 
263
- static void verify_data(char *data, size_t size, unsigned long seq)
372
+ static void verify_data(__u8 *data, size_t size, unsigned long seq)
264
373
  {
265
- int i;
374
+ size_t i;
266
375
 
267
376
  if (!cfg_verify_data)
268
377
  return;
269
378
 
270
379
  for (i = 0; i < size; i++) {
271
- char expected = 'a' + (seq + i) % 26;
380
+ __u8 expected = (__u8)'a' + (seq + i) % 26;
381
+ __u8 v = data[i];
272
382
 
273
- if (data[i] != expected)
274
- t_error(1, 0, "payload mismatch at %i: expected %i vs got %i, seq %li",
275
- i, expected, data[i], seq);
383
+ if (v != expected)
384
+ t_error(1, 0, "payload mismatch at %u: expected %u vs got %u, diff %i, base seq %lu, seq %lu",
385
+ (unsigned)i, expected, v, (int)expected - v,
386
+ seq, seq + i);
276
387
  }
277
388
  }
278
389
 
279
- static void process_recvzc(struct io_uring __attribute__((unused)) *ring,
280
- struct io_uring_cqe *cqe)
390
+ static unsigned rq_nr_queued(struct io_uring_zcrx_rq *rq)
391
+ {
392
+ return rq->rq_tail - io_uring_smp_load_acquire(rq->khead);
393
+ }
394
+
395
+ static inline void fill_rqe(const struct io_uring_cqe *cqe,
396
+ struct io_uring_zcrx_rqe *rqe)
397
+ {
398
+ const struct io_uring_zcrx_cqe *rcqe = (void *)(cqe + 1);
399
+
400
+ rqe->off = (rcqe->off & ~IORING_ZCRX_AREA_MASK) | area_token;
401
+ rqe->len = cqe->res;
402
+ }
403
+
404
+ static void return_buffer(struct io_uring_zcrx_rq *rq_ring,
405
+ const struct io_uring_cqe *cqe)
281
406
  {
282
- unsigned rq_mask = rq_ring.ring_entries - 1;
283
- struct io_uring_zcrx_cqe *rcqe;
284
407
  struct io_uring_zcrx_rqe *rqe;
408
+ unsigned rq_mask;
409
+
410
+ if (rq_nr_queued(rq_ring) == rq_ring->ring_entries) {
411
+ printf("refill queue is full, drop the buffer\n");
412
+ return;
413
+ }
414
+
415
+ rq_mask = rq_ring->ring_entries - 1;
416
+ /* processed, return back to the kernel */
417
+ rqe = &rq_ring->rqes[rq_ring->rq_tail & rq_mask];
418
+ fill_rqe(cqe, rqe);
419
+ io_uring_smp_store_release(rq_ring->ktail, ++rq_ring->rq_tail);
420
+ }
421
+
422
+ static void process_recvzc_error(struct io_uring *ring,
423
+ struct zc_conn *conn, int ret)
424
+ {
425
+ if (ret == -ENOSPC) {
426
+ size_t left = 0;
427
+
428
+ if (cfg_size) {
429
+ left = cfg_size - conn->received;
430
+ if (left == 0)
431
+ t_error(1, 0, "ENOSPC for a finished request");
432
+ }
433
+
434
+ add_recvzc(ring, conn, left);
435
+ return;
436
+ }
437
+
438
+ if (ret != 0)
439
+ t_error(1, 0, "invalid final recvzc ret %i", ret);
440
+ if (cfg_size && conn->received != cfg_size)
441
+ t_error(1, 0, "total receive size mismatch %lu / %lu",
442
+ conn->received, cfg_size);
443
+
444
+ printf("Connection terminated: received %lu, cqes %i, nr requeues %i\n",
445
+ conn->received,
446
+ conn->stat_nr_cqes,
447
+ conn->stat_nr_reqs - 1);
448
+
449
+ close(conn->sockfd);
450
+ free(conn);
451
+ }
452
+
453
+ static void process_recvzc(struct io_uring *ring,
454
+ struct io_uring_cqe *cqe)
455
+ {
456
+ struct zc_conn *conn = get_connection(cqe->user_data);
457
+ const struct io_uring_zcrx_cqe *rcqe;
285
458
  uint64_t mask;
286
- char *data;
459
+ __u8 *data;
460
+
461
+ conn->stat_nr_cqes++;
287
462
 
288
463
  if (!(cqe->flags & IORING_CQE_F_MORE)) {
289
- if (!cfg_size || cqe->res != 0)
290
- t_error(1, 0, "invalid final recvzc ret %i", cqe->res);
291
- if (received != cfg_size)
292
- t_error(1, 0, "total receive size mismatch %lu / %lu",
293
- received, cfg_size);
294
- stop = true;
464
+ process_recvzc_error(ring, conn, cqe->res);
295
465
  return;
296
466
  }
297
467
  if (cqe->res < 0)
@@ -299,24 +469,22 @@ static void process_recvzc(struct io_uring __attribute__((unused)) *ring,
299
469
 
300
470
  rcqe = (struct io_uring_zcrx_cqe *)(cqe + 1);
301
471
  mask = (1ULL << IORING_ZCRX_AREA_SHIFT) - 1;
302
- data = (char *)area_ptr + (rcqe->off & mask);
472
+ data = (__u8 *)area_ptr + (rcqe->off & mask);
303
473
 
304
- verify_data(data, cqe->res, received);
305
- received += cqe->res;
306
-
307
- /* processed, return back to the kernel */
308
- rqe = &rq_ring.rqes[rq_ring.rq_tail & rq_mask];
309
- rqe->off = (rcqe->off & ~IORING_ZCRX_AREA_MASK) | area_token;
310
- rqe->len = cqe->res;
311
- io_uring_smp_store_release(rq_ring.ktail, ++rq_ring.rq_tail);
474
+ verify_data(data, cqe->res, conn->received);
475
+ conn->received += cqe->res;
476
+ return_buffer(&rq_ring, cqe);
312
477
  }
313
478
 
314
479
  static void server_loop(struct io_uring *ring)
315
480
  {
316
481
  struct io_uring_cqe *cqe;
317
482
  unsigned int head, count = 0;
483
+ int ret;
318
484
 
319
- io_uring_submit_and_wait(ring, 1);
485
+ ret = io_uring_submit_and_wait(ring, 1);
486
+ if (ret < 0 && ret != -ETIME)
487
+ t_error(1, ret, "io_uring_submit_and_wait failed\n");
320
488
 
321
489
  io_uring_for_each_cqe(ring, head, cqe) {
322
490
  switch (cqe->user_data & REQ_TYPE_MASK) {
@@ -336,41 +504,46 @@ static void server_loop(struct io_uring *ring)
336
504
 
337
505
  static void run_server(void)
338
506
  {
339
- unsigned int flags = 0;
507
+ struct io_uring_params p;
340
508
  struct io_uring ring;
341
- int fd, enable, ret;
509
+ int enable, ret;
342
510
 
343
- fd = socket(AF_INET6, SOCK_STREAM, 0);
344
- if (fd == -1)
511
+ listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
512
+ if (listen_fd == -1)
345
513
  t_error(1, 0, "socket()");
346
514
 
347
515
  enable = 1;
348
- ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
516
+ ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
349
517
  if (ret < 0)
350
518
  t_error(1, 0, "setsockopt(SO_REUSEADDR)");
351
519
 
352
- ret = bind(fd, (struct sockaddr *)&cfg_addr, sizeof(cfg_addr));
520
+ ret = bind(listen_fd, (struct sockaddr *)&cfg_addr, sizeof(cfg_addr));
353
521
  if (ret < 0)
354
522
  t_error(1, 0, "bind()");
355
523
 
356
- if (listen(fd, 1024) < 0)
524
+ if (listen(listen_fd, 1024) < 0)
357
525
  t_error(1, 0, "listen()");
358
526
 
359
- flags |= IORING_SETUP_COOP_TASKRUN;
360
- flags |= IORING_SETUP_SINGLE_ISSUER;
361
- flags |= IORING_SETUP_DEFER_TASKRUN;
362
- flags |= IORING_SETUP_SUBMIT_ALL;
363
- flags |= IORING_SETUP_CQE32;
527
+ memset(&p, 0, sizeof(p));
528
+ p.flags |= IORING_SETUP_COOP_TASKRUN;
529
+ p.flags |= IORING_SETUP_SINGLE_ISSUER;
530
+ p.flags |= IORING_SETUP_DEFER_TASKRUN;
531
+ p.flags |= IORING_SETUP_SUBMIT_ALL;
532
+ p.flags |= IORING_SETUP_CQE32;
533
+ p.flags |= IORING_SETUP_CQSIZE;
534
+ p.cq_entries = cfg_cq_entries;
364
535
 
365
- ret = io_uring_queue_init(512, &ring, flags);
536
+ ret = io_uring_queue_init_params(8, &ring, &p);
366
537
  if (ret)
367
538
  t_error(1, ret, "ring init failed");
368
539
 
369
540
  setup_zcrx(&ring);
370
- add_accept(&ring, fd);
541
+ add_accept(&ring, listen_fd);
371
542
 
372
543
  while (!stop)
373
544
  server_loop(&ring);
545
+
546
+ close(listen_fd);
374
547
  }
375
548
 
376
549
  static void usage(const char *filepath)
@@ -386,7 +559,7 @@ static void parse_opts(int argc, char **argv)
386
559
  if (argc <= 1)
387
560
  usage(argv[0]);
388
561
 
389
- while ((c = getopt(argc, argv, "vp:i:q:s:r:A:")) != -1) {
562
+ while ((c = getopt(argc, argv, "vp:i:q:s:r:A:S:C:R:c:")) != -1) {
390
563
  switch (c) {
391
564
  case 'p':
392
565
  cfg_port = strtoul(optarg, NULL, 0);
@@ -408,14 +581,32 @@ static void parse_opts(int argc, char **argv)
408
581
  if (cfg_rq_alloc_mode >= __RQ_ALLOC_MAX)
409
582
  t_error(1, 0, "invalid RQ allocation mode");
410
583
  break;
584
+ case 'S':
585
+ cfg_area_size = strtoul(optarg, NULL, 0);
586
+ break;
411
587
  case 'A':
412
588
  cfg_area_type = strtoul(optarg, NULL, 0);
413
589
  if (cfg_area_type >= __AREA_TYPE_MAX)
414
590
  t_error(1, 0, "Invalid area type");
415
591
  break;
592
+ case 'C':
593
+ cfg_cq_entries = strtoul(optarg, NULL, 0);
594
+ break;
595
+ case 'R':
596
+ cfg_rq_entries = strtoul(optarg, NULL, 0);
597
+ break;
598
+ case 'c':
599
+ cfg_affinity_mode = strtoul(optarg, NULL, 0);
600
+ if (cfg_affinity_mode >= __AFFINITY_MODE_MAX)
601
+ t_error(1, 0, "Invalid affinity mode");
416
602
  }
417
603
  }
418
604
 
605
+ if (!cfg_ifname)
606
+ t_error(1, -EINVAL, "Interface is not specified");
607
+ if (cfg_queue_id == -1)
608
+ t_error(1, -EINVAL, "Queue idx is not specified");
609
+
419
610
  memset(addr6, 0, sizeof(*addr6));
420
611
  addr6->sin6_family = AF_INET6;
421
612
  addr6->sin6_port = htons(cfg_port);
@@ -1,5 +1,5 @@
1
1
  Name: liburing
2
- Version: 2.13
2
+ Version: 2.14
3
3
  Release: 1%{?dist}
4
4
  Summary: Linux-native io_uring I/O access library
5
5
  License: (GPLv2 with exceptions and LGPLv2+) or MIT
@@ -233,6 +233,18 @@ enum io_uring_sqe_flags_bit {
233
233
  */
234
234
  #define IORING_SETUP_SQE_MIXED (1U << 19)
235
235
 
236
+ /*
237
+ * When set, io_uring ignores SQ head and tail and fetches SQEs to submit
238
+ * starting from index 0 instead from the index stored in the head pointer.
239
+ * IOW, the user should place all SQE at the beginning of the SQ memory
240
+ * before issuing a submission syscall.
241
+ *
242
+ * It requires IORING_SETUP_NO_SQARRAY and is incompatible with
243
+ * IORING_SETUP_SQPOLL. The user must also never change the SQ head and tail
244
+ * values and keep it set to 0. Any other value is undefined behaviour.
245
+ */
246
+ #define IORING_SETUP_SQ_REWIND (1U << 20)
247
+
236
248
  enum io_uring_op {
237
249
  IORING_OP_NOP,
238
250
  IORING_OP_READV,