@@ -61,6 +61,9 @@ static int cfg_port = 8000;
6161static int cfg_payload_len ;
6262static const char * cfg_ifname ;
6363static int cfg_queue_id = -1 ;
64+ static bool cfg_oneshot ;
65+ static int cfg_oneshot_recvs ;
66+ static int cfg_send_size = SEND_SIZE ;
6467static struct sockaddr_in6 cfg_addr ;
6568
6669static char payload [SEND_SIZE ] __attribute__((aligned (PAGE_SIZE )));
@@ -196,6 +199,17 @@ static void add_recvzc(struct io_uring *ring, int sockfd)
196199 sqe -> user_data = 2 ;
197200}
198201
202+ static void add_recvzc_oneshot (struct io_uring * ring , int sockfd , size_t len )
203+ {
204+ struct io_uring_sqe * sqe ;
205+
206+ sqe = io_uring_get_sqe (ring );
207+
208+ io_uring_prep_rw (IORING_OP_RECV_ZC , sqe , sockfd , NULL , len , 0 );
209+ sqe -> ioprio |= IORING_RECV_MULTISHOT ;
210+ sqe -> user_data = 2 ;
211+ }
212+
199213static void process_accept (struct io_uring * ring , struct io_uring_cqe * cqe )
200214{
201215 if (cqe -> res < 0 )
@@ -204,7 +218,10 @@ static void process_accept(struct io_uring *ring, struct io_uring_cqe *cqe)
204218 error (1 , 0 , "Unexpected second connection" );
205219
206220 connfd = cqe -> res ;
207- add_recvzc (ring , connfd );
221+ if (cfg_oneshot )
222+ add_recvzc_oneshot (ring , connfd , PAGE_SIZE );
223+ else
224+ add_recvzc (ring , connfd );
208225}
209226
210227static void process_recvzc (struct io_uring * ring , struct io_uring_cqe * cqe )
@@ -218,16 +235,22 @@ static void process_recvzc(struct io_uring *ring, struct io_uring_cqe *cqe)
218235 ssize_t n ;
219236 int i ;
220237
221- if (cqe -> res == 0 && cqe -> flags == 0 ) {
238+ if (cqe -> res == 0 && cqe -> flags == 0 && cfg_oneshot_recvs == 0 ) {
222239 stop = true;
223240 return ;
224241 }
225242
226243 if (cqe -> res < 0 )
227244 error (1 , 0 , "recvzc(): %d" , cqe -> res );
228245
229- if (!(cqe -> flags & IORING_CQE_F_MORE ))
246+ if (cfg_oneshot ) {
247+ if (cqe -> res == 0 && cqe -> flags == 0 && cfg_oneshot_recvs ) {
248+ add_recvzc_oneshot (ring , connfd , PAGE_SIZE );
249+ cfg_oneshot_recvs -- ;
250+ }
251+ } else if (!(cqe -> flags & IORING_CQE_F_MORE )) {
230252 add_recvzc (ring , connfd );
253+ }
231254
232255 rcqe = (struct io_uring_zcrx_cqe * )(cqe + 1 );
233256
@@ -237,7 +260,7 @@ static void process_recvzc(struct io_uring *ring, struct io_uring_cqe *cqe)
237260
238261 for (i = 0 ; i < n ; i ++ ) {
239262 if (* (data + i ) != payload [(received + i )])
240- error (1 , 0 , "payload mismatch" );
263+ error (1 , 0 , "payload mismatch at " , i );
241264 }
242265 received += n ;
243266
@@ -313,7 +336,7 @@ static void run_server(void)
313336
314337static void run_client (void )
315338{
316- ssize_t to_send = SEND_SIZE ;
339+ ssize_t to_send = cfg_send_size ;
317340 ssize_t sent = 0 ;
318341 ssize_t chunk , res ;
319342 int fd ;
@@ -360,7 +383,7 @@ static void parse_opts(int argc, char **argv)
360383 usage (argv [0 ]);
361384 cfg_payload_len = max_payload_len ;
362385
363- while ((c = getopt (argc , argv , "46sch :p:l:i:q:" )) != -1 ) {
386+ while ((c = getopt (argc , argv , "sch :p:l:i:q:o:z :" )) != -1 ) {
364387 switch (c ) {
365388 case 's' :
366389 if (cfg_client )
@@ -387,6 +410,14 @@ static void parse_opts(int argc, char **argv)
387410 case 'q' :
388411 cfg_queue_id = strtoul (optarg , NULL , 0 );
389412 break ;
413+ case 'o' : {
414+ cfg_oneshot = true;
415+ cfg_oneshot_recvs = strtoul (optarg , NULL , 0 );
416+ break ;
417+ }
418+ case 'z' :
419+ cfg_send_size = strtoul (optarg , NULL , 0 );
420+ break ;
390421 }
391422 }
392423
0 commit comments