aboutsummaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2018-01-22 13:35:45 -0500
committerDaniel Borkmann <daniel@iogearbox.net>2018-01-24 04:46:58 -0500
commiteaf8c6eec5f9ab5d9d7155d7041fb7eea7028052 (patch)
tree4869d078a6e12252ddb73936ea9f4388798fef83 /samples
parent6627426fa2741866f1bdd194216a91a82ec063e4 (diff)
bpf: add sendmsg option for testing BPF programs
When testing BPF programs using sockmap I often want to have more control over how sendmsg is exercised. This becomes even more useful as new sockmap program types are added. This adds a test type option to select type of test to run. Currently, only "ping" and "sendmsg" are supported, but more can be added as needed. The new help argument gives the following, Usage: ./sockmap --cgroup <cgroup_path> options: --help -h --cgroup -c --rate -r --verbose -v --iov_count -i --length -l --test -t Signed-off-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'samples')
-rw-r--r--samples/sockmap/sockmap_user.c148
1 files changed, 145 insertions, 3 deletions
diff --git a/samples/sockmap/sockmap_user.c b/samples/sockmap/sockmap_user.c
index ffd1d127a9d3..ccc717349eba 100644
--- a/samples/sockmap/sockmap_user.c
+++ b/samples/sockmap/sockmap_user.c
@@ -56,6 +56,9 @@ static const struct option long_options[] = {
56 {"cgroup", required_argument, NULL, 'c' }, 56 {"cgroup", required_argument, NULL, 'c' },
57 {"rate", required_argument, NULL, 'r' }, 57 {"rate", required_argument, NULL, 'r' },
58 {"verbose", no_argument, NULL, 'v' }, 58 {"verbose", no_argument, NULL, 'v' },
59 {"iov_count", required_argument, NULL, 'i' },
60 {"length", required_argument, NULL, 'l' },
61 {"test", required_argument, NULL, 't' },
59 {0, 0, NULL, 0 } 62 {0, 0, NULL, 0 }
60}; 63};
61 64
@@ -182,6 +185,118 @@ static int sockmap_init_sockets(void)
182 return 0; 185 return 0;
183} 186}
184 187
188struct msg_stats {
189 size_t bytes_sent;
190 size_t bytes_recvd;
191};
192
193static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
194 struct msg_stats *s, bool tx)
195{
196 struct msghdr msg = {0};
197 struct iovec *iov;
198 int i, flags = 0;
199
200 iov = calloc(iov_count, sizeof(struct iovec));
201 if (!iov)
202 return errno;
203
204 for (i = 0; i < iov_count; i++) {
205 char *d = calloc(iov_length, sizeof(char));
206
207 if (!d) {
208 fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
209 goto out_errno;
210 }
211 iov[i].iov_base = d;
212 iov[i].iov_len = iov_length;
213 }
214
215 msg.msg_iov = iov;
216 msg.msg_iovlen = iov_count;
217
218 if (tx) {
219 for (i = 0; i < cnt; i++) {
220 int sent = sendmsg(fd, &msg, flags);
221
222 if (sent < 0) {
223 perror("send loop error:");
224 goto out_errno;
225 }
226 s->bytes_sent += sent;
227 }
228 } else {
229 int slct, recv, max_fd = fd;
230 struct timeval timeout;
231 float total_bytes;
232 fd_set w;
233
234 total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
235 while (s->bytes_recvd < total_bytes) {
236 timeout.tv_sec = 1;
237 timeout.tv_usec = 0;
238
239 /* FD sets */
240 FD_ZERO(&w);
241 FD_SET(fd, &w);
242
243 slct = select(max_fd + 1, &w, NULL, NULL, &timeout);
244 if (slct == -1) {
245 perror("select()");
246 goto out_errno;
247 } else if (!slct) {
248 fprintf(stderr, "unexpected timeout\n");
249 errno = -EIO;
250 goto out_errno;
251 }
252
253 recv = recvmsg(fd, &msg, flags);
254 if (recv < 0) {
255 if (errno != EWOULDBLOCK) {
256 perror("recv failed()\n");
257 goto out_errno;
258 }
259 }
260
261 s->bytes_recvd += recv;
262 }
263 }
264
265 for (i = 0; i < iov_count; i++)
266 free(iov[i].iov_base);
267 free(iov);
268 return 0;
269out_errno:
270 for (i = 0; i < iov_count; i++)
271 free(iov[i].iov_base);
272 free(iov);
273 return errno;
274}
275
276static int sendmsg_test(int iov_count, int iov_buf, int cnt, int verbose)
277{
278 struct msg_stats s = {0};
279 int err;
280
281 err = msg_loop(c1, iov_count, iov_buf, cnt, &s, true);
282 if (err) {
283 fprintf(stderr,
284 "msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n",
285 iov_count, iov_buf, cnt, err);
286 return err;
287 }
288
289 err = msg_loop(p2, iov_count, iov_buf, cnt, &s, false);
290 if (err)
291 fprintf(stderr,
292 "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
293 iov_count, iov_buf, cnt, err);
294
295 fprintf(stdout, "sendmsg: TX_bytes %zu RX_bytes %zu\n",
296 s.bytes_sent, s.bytes_recvd);
297 return err;
298}
299
185static int forever_ping_pong(int rate, int verbose) 300static int forever_ping_pong(int rate, int verbose)
186{ 301{
187 struct timeval timeout; 302 struct timeval timeout;
@@ -257,13 +372,19 @@ static int forever_ping_pong(int rate, int verbose)
257 return 0; 372 return 0;
258} 373}
259 374
375enum {
376 PING_PONG,
377 SENDMSG,
378};
379
260int main(int argc, char **argv) 380int main(int argc, char **argv)
261{ 381{
262 int rate = 1, verbose = 0; 382 int iov_count = 1, length = 1024, rate = 1, verbose = 0;
263 int opt, longindex, err, cg_fd = 0; 383 int opt, longindex, err, cg_fd = 0;
384 int test = PING_PONG;
264 char filename[256]; 385 char filename[256];
265 386
266 while ((opt = getopt_long(argc, argv, "hvc:r:", 387 while ((opt = getopt_long(argc, argv, "hvc:r:i:l:t:",
267 long_options, &longindex)) != -1) { 388 long_options, &longindex)) != -1) {
268 switch (opt) { 389 switch (opt) {
269 /* Cgroup configuration */ 390 /* Cgroup configuration */
@@ -282,6 +403,22 @@ int main(int argc, char **argv)
282 case 'v': 403 case 'v':
283 verbose = 1; 404 verbose = 1;
284 break; 405 break;
406 case 'i':
407 iov_count = atoi(optarg);
408 break;
409 case 'l':
410 length = atoi(optarg);
411 break;
412 case 't':
413 if (strcmp(optarg, "ping") == 0) {
414 test = PING_PONG;
415 } else if (strcmp(optarg, "sendmsg") == 0) {
416 test = SENDMSG;
417 } else {
418 usage(argv);
419 return -1;
420 }
421 break;
285 case 'h': 422 case 'h':
286 default: 423 default:
287 usage(argv); 424 usage(argv);
@@ -339,7 +476,12 @@ int main(int argc, char **argv)
339 goto out; 476 goto out;
340 } 477 }
341 478
342 err = forever_ping_pong(rate, verbose); 479 if (test == PING_PONG)
480 err = forever_ping_pong(rate, verbose);
481 else if (test == SENDMSG)
482 err = sendmsg_test(iov_count, length, rate, verbose);
483 else
484 fprintf(stderr, "unknown test\n");
343out: 485out:
344 close(s1); 486 close(s1);
345 close(s2); 487 close(s2);