31
31
#include <sys/wait.h>
32
32
#include <unistd.h>
33
33
34
+ #ifndef UDP_GRO
35
+ #define UDP_GRO 104
36
+ #endif
37
+
34
38
static int cfg_port = 8000 ;
35
39
static bool cfg_tcp ;
36
40
static bool cfg_verify ;
41
+ static bool cfg_read_all ;
42
+ static bool cfg_gro_segment ;
37
43
38
44
static bool interrupted ;
39
45
static unsigned long packets , bytes ;
@@ -63,14 +69,16 @@ static void do_poll(int fd)
63
69
64
70
do {
65
71
ret = poll (& pfd , 1 , 10 );
72
+ if (interrupted )
73
+ break ;
66
74
if (ret == -1 )
67
75
error (1 , errno , "poll" );
68
76
if (ret == 0 )
69
77
continue ;
70
78
if (pfd .revents != POLLIN )
71
79
error (1 , errno , "poll: 0x%x expected 0x%x\n" ,
72
80
pfd .revents , POLLIN );
73
- } while (!ret && ! interrupted );
81
+ } while (!ret );
74
82
}
75
83
76
84
static int do_socket (bool do_tcp )
@@ -102,6 +110,8 @@ static int do_socket(bool do_tcp)
102
110
error (1 , errno , "listen" );
103
111
104
112
do_poll (accept_fd );
113
+ if (interrupted )
114
+ exit (0 );
105
115
106
116
fd = accept (accept_fd , NULL , NULL );
107
117
if (fd == -1 )
@@ -167,18 +177,18 @@ static void do_verify_udp(const char *data, int len)
167
177
/* Flush all outstanding datagrams. Verify first few bytes of each. */
168
178
static void do_flush_udp (int fd )
169
179
{
170
- static char rbuf [ETH_DATA_LEN ];
180
+ static char rbuf [ETH_MAX_MTU ];
171
181
int ret , len , budget = 256 ;
172
182
173
- len = cfg_verify ? sizeof (rbuf ) : 0 ;
183
+ len = cfg_read_all ? sizeof (rbuf ) : 0 ;
174
184
while (budget -- ) {
175
185
/* MSG_TRUNC will make return value full datagram length */
176
186
ret = recv (fd , rbuf , len , MSG_TRUNC | MSG_DONTWAIT );
177
187
if (ret == -1 && errno == EAGAIN )
178
188
return ;
179
189
if (ret == -1 )
180
190
error (1 , errno , "recv" );
181
- if (len ) {
191
+ if (len && cfg_verify ) {
182
192
if (ret == 0 )
183
193
error (1 , errno , "recv: 0 byte datagram\n" );
184
194
@@ -192,23 +202,30 @@ static void do_flush_udp(int fd)
192
202
193
203
static void usage (const char * filepath )
194
204
{
195
- error (1 , 0 , "Usage: %s [-tv ] [-p port]" , filepath );
205
+ error (1 , 0 , "Usage: %s [-Grtv ] [-p port]" , filepath );
196
206
}
197
207
198
208
static void parse_opts (int argc , char * * argv )
199
209
{
200
210
int c ;
201
211
202
- while ((c = getopt (argc , argv , "ptv " )) != -1 ) {
212
+ while ((c = getopt (argc , argv , "Gp:rtv " )) != -1 ) {
203
213
switch (c ) {
214
+ case 'G' :
215
+ cfg_gro_segment = true;
216
+ break ;
204
217
case 'p' :
205
- cfg_port = htons (strtoul (optarg , NULL , 0 ));
218
+ cfg_port = strtoul (optarg , NULL , 0 );
219
+ break ;
220
+ case 'r' :
221
+ cfg_read_all = true;
206
222
break ;
207
223
case 't' :
208
224
cfg_tcp = true;
209
225
break ;
210
226
case 'v' :
211
227
cfg_verify = true;
228
+ cfg_read_all = true;
212
229
break ;
213
230
}
214
231
}
@@ -227,6 +244,12 @@ static void do_recv(void)
227
244
228
245
fd = do_socket (cfg_tcp );
229
246
247
+ if (cfg_gro_segment && !cfg_tcp ) {
248
+ int val = 1 ;
249
+ if (setsockopt (fd , IPPROTO_UDP , UDP_GRO , & val , sizeof (val )))
250
+ error (1 , errno , "setsockopt UDP_GRO" );
251
+ }
252
+
230
253
treport = gettimeofday_ms () + 1000 ;
231
254
do {
232
255
do_poll (fd );
0 commit comments