@@ -51,6 +51,7 @@ enum cfg_mode {
51
51
CFG_MODE_POLL ,
52
52
CFG_MODE_MMAP ,
53
53
CFG_MODE_SENDFILE ,
54
+ CFG_MODE_SPLICE ,
54
55
};
55
56
56
57
enum cfg_peek {
@@ -123,7 +124,7 @@ static void die_usage(void)
123
124
fprintf (stderr , "\t-j -- add additional sleep at connection start and tear down "
124
125
"-- for MPJ tests\n" );
125
126
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" );
127
128
fprintf (stderr , "\t-M mark -- set socket packet mark\n" );
128
129
fprintf (stderr , "\t-o option -- test sockopt <option>\n" );
129
130
fprintf (stderr , "\t-p num -- use port num\n" );
@@ -925,6 +926,55 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
925
926
return err ;
926
927
}
927
928
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
+
928
978
static int copyfd_io (int infd , int peerfd , int outfd , bool close_peerfd , struct wstate * winfo )
929
979
{
930
980
bool in_closed_after_out = false;
@@ -957,6 +1007,14 @@ static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd, struct
957
1007
& in_closed_after_out , winfo );
958
1008
break ;
959
1009
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
+
960
1018
default :
961
1019
fprintf (stderr , "Invalid mode %d\n" , cfg_mode );
962
1020
@@ -1361,12 +1419,15 @@ int parse_mode(const char *mode)
1361
1419
return CFG_MODE_MMAP ;
1362
1420
if (!strcasecmp (mode , "sendfile" ))
1363
1421
return CFG_MODE_SENDFILE ;
1422
+ if (!strcasecmp (mode , "splice" ))
1423
+ return CFG_MODE_SPLICE ;
1364
1424
1365
1425
fprintf (stderr , "Unknown test mode: %s\n" , mode );
1366
1426
fprintf (stderr , "Supported modes are:\n" );
1367
1427
fprintf (stderr , "\t\t\"poll\" - interleaved read/write using poll()\n" );
1368
1428
fprintf (stderr , "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n" );
1369
1429
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" );
1370
1431
1371
1432
die_usage ();
1372
1433
0 commit comments