@@ -51,6 +51,7 @@ enum cfg_mode {
5151 CFG_MODE_POLL ,
5252 CFG_MODE_MMAP ,
5353 CFG_MODE_SENDFILE ,
54+ CFG_MODE_SPLICE ,
5455};
5556
5657enum cfg_peek {
@@ -123,7 +124,7 @@ static void die_usage(void)
123124 fprintf (stderr , "\t-j -- add additional sleep at connection start and tear down "
124125 "-- for MPJ tests\n" );
125126 fprintf (stderr , "\t-l -- listens mode, accepts incoming connection\n" );
126- fprintf (stderr , "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n" );
127+ fprintf (stderr , "\t-m [poll|mmap|sendfile|splice ] -- use poll(default)/mmap+write/sendfile/splice \n" );
127128 fprintf (stderr , "\t-M mark -- set socket packet mark\n" );
128129 fprintf (stderr , "\t-o option -- test sockopt <option>\n" );
129130 fprintf (stderr , "\t-p num -- use port num\n" );
@@ -925,6 +926,55 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
925926 return err ;
926927}
927928
929+ static int do_splice (const int infd , const int outfd , const size_t len ,
930+ struct wstate * winfo )
931+ {
932+ int pipefd [2 ];
933+ ssize_t bytes ;
934+ int err ;
935+
936+ err = pipe (pipefd );
937+ if (err )
938+ return err ;
939+
940+ while ((bytes = splice (infd , NULL , pipefd [1 ], NULL ,
941+ len - winfo -> total_len ,
942+ SPLICE_F_MOVE | SPLICE_F_MORE )) > 0 ) {
943+ splice (pipefd [0 ], NULL , outfd , NULL , bytes ,
944+ SPLICE_F_MOVE | SPLICE_F_MORE );
945+ }
946+
947+ close (pipefd [0 ]);
948+ close (pipefd [1 ]);
949+
950+ return 0 ;
951+ }
952+
953+ static int copyfd_io_splice (int infd , int peerfd , int outfd , unsigned int size ,
954+ bool * in_closed_after_out , struct wstate * winfo )
955+ {
956+ int err ;
957+
958+ if (listen_mode ) {
959+ err = do_splice (peerfd , outfd , size , winfo );
960+ if (err )
961+ return err ;
962+
963+ err = do_splice (infd , peerfd , size , winfo );
964+ } else {
965+ err = do_splice (infd , peerfd , size , winfo );
966+ if (err )
967+ return err ;
968+
969+ shut_wr (peerfd );
970+
971+ err = do_splice (peerfd , outfd , size , winfo );
972+ * in_closed_after_out = true;
973+ }
974+
975+ return err ;
976+ }
977+
928978static int copyfd_io (int infd , int peerfd , int outfd , bool close_peerfd , struct wstate * winfo )
929979{
930980 bool in_closed_after_out = false;
@@ -957,6 +1007,14 @@ static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd, struct
9571007 & in_closed_after_out , winfo );
9581008 break ;
9591009
1010+ case CFG_MODE_SPLICE :
1011+ file_size = get_infd_size (infd );
1012+ if (file_size < 0 )
1013+ return file_size ;
1014+ ret = copyfd_io_splice (infd , peerfd , outfd , file_size ,
1015+ & in_closed_after_out , winfo );
1016+ break ;
1017+
9601018 default :
9611019 fprintf (stderr , "Invalid mode %d\n" , cfg_mode );
9621020
@@ -1361,12 +1419,15 @@ int parse_mode(const char *mode)
13611419 return CFG_MODE_MMAP ;
13621420 if (!strcasecmp (mode , "sendfile" ))
13631421 return CFG_MODE_SENDFILE ;
1422+ if (!strcasecmp (mode , "splice" ))
1423+ return CFG_MODE_SPLICE ;
13641424
13651425 fprintf (stderr , "Unknown test mode: %s\n" , mode );
13661426 fprintf (stderr , "Supported modes are:\n" );
13671427 fprintf (stderr , "\t\t\"poll\" - interleaved read/write using poll()\n" );
13681428 fprintf (stderr , "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n" );
13691429 fprintf (stderr , "\t\t\"sendfile\" - send entire input file (sendfile), then read response (-l will read input first)\n" );
1430+ fprintf (stderr , "\t\t\"splice\" - send entire input file (splice), then read response (-l will read input first)\n" );
13701431
13711432 die_usage ();
13721433
0 commit comments