Commit 6627426f authored by John Fastabend's avatar John Fastabend Committed by Daniel Borkmann

bpf: refactor sockmap sample program update for arg parsing

sockmap sample program takes arguments from cmd line but it reads them
in using offsets into the array. Because we want to add more arguments
in the future lets do proper argument handling.

Also refactor code to pull apart sock init and ping/pong test. This
allows us to add new tests in the future.
Signed-off-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 31e95b61
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include <assert.h> #include <assert.h>
#include <libgen.h> #include <libgen.h>
#include <getopt.h>
#include "../bpf/bpf_load.h" #include "../bpf/bpf_load.h"
#include "../bpf/bpf_util.h" #include "../bpf/bpf_util.h"
#include "../bpf/libbpf.h" #include "../bpf/libbpf.h"
...@@ -46,15 +48,39 @@ void running_handler(int a); ...@@ -46,15 +48,39 @@ void running_handler(int a);
#define S1_PORT 10000 #define S1_PORT 10000
#define S2_PORT 10001 #define S2_PORT 10001
static int sockmap_test_sockets(int rate, int dot) /* global sockets */
int s1, s2, c1, c2, p1, p2;
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h' },
{"cgroup", required_argument, NULL, 'c' },
{"rate", required_argument, NULL, 'r' },
{"verbose", no_argument, NULL, 'v' },
{0, 0, NULL, 0 }
};
static void usage(char *argv[])
{ {
int i, sc, err, max_fd, one = 1; int i;
int s1, s2, c1, c2, p1, p2;
printf(" Usage: %s --cgroup <cgroup_path>\n", argv[0]);
printf(" options:\n");
for (i = 0; long_options[i].name != 0; i++) {
printf(" --%-12s", long_options[i].name);
if (long_options[i].flag != NULL)
printf(" flag (internal value:%d)\n",
*long_options[i].flag);
else
printf(" -%c\n", long_options[i].val);
}
printf("\n");
}
static int sockmap_init_sockets(void)
{
int i, err, one = 1;
struct sockaddr_in addr; struct sockaddr_in addr;
struct timeval timeout;
char buf[1024] = {0};
int *fds[4] = {&s1, &s2, &c1, &c2}; int *fds[4] = {&s1, &s2, &c1, &c2};
fd_set w;
s1 = s2 = p1 = p2 = c1 = c2 = 0; s1 = s2 = p1 = p2 = c1 = c2 = 0;
...@@ -63,8 +89,7 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -63,8 +89,7 @@ static int sockmap_test_sockets(int rate, int dot)
*fds[i] = socket(AF_INET, SOCK_STREAM, 0); *fds[i] = socket(AF_INET, SOCK_STREAM, 0);
if (*fds[i] < 0) { if (*fds[i] < 0) {
perror("socket s1 failed()"); perror("socket s1 failed()");
err = *fds[i]; return errno;
goto out;
} }
} }
...@@ -74,7 +99,7 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -74,7 +99,7 @@ static int sockmap_test_sockets(int rate, int dot)
(char *)&one, sizeof(one)); (char *)&one, sizeof(one));
if (err) { if (err) {
perror("setsockopt failed()"); perror("setsockopt failed()");
goto out; return errno;
} }
} }
...@@ -83,7 +108,7 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -83,7 +108,7 @@ static int sockmap_test_sockets(int rate, int dot)
err = ioctl(*fds[i], FIONBIO, (char *)&one); err = ioctl(*fds[i], FIONBIO, (char *)&one);
if (err < 0) { if (err < 0) {
perror("ioctl s1 failed()"); perror("ioctl s1 failed()");
goto out; return errno;
} }
} }
...@@ -96,14 +121,14 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -96,14 +121,14 @@ static int sockmap_test_sockets(int rate, int dot)
err = bind(s1, (struct sockaddr *)&addr, sizeof(addr)); err = bind(s1, (struct sockaddr *)&addr, sizeof(addr));
if (err < 0) { if (err < 0) {
perror("bind s1 failed()\n"); perror("bind s1 failed()\n");
goto out; return errno;
} }
addr.sin_port = htons(S2_PORT); addr.sin_port = htons(S2_PORT);
err = bind(s2, (struct sockaddr *)&addr, sizeof(addr)); err = bind(s2, (struct sockaddr *)&addr, sizeof(addr));
if (err < 0) { if (err < 0) {
perror("bind s2 failed()\n"); perror("bind s2 failed()\n");
goto out; return errno;
} }
/* Listen server sockets */ /* Listen server sockets */
...@@ -111,14 +136,14 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -111,14 +136,14 @@ static int sockmap_test_sockets(int rate, int dot)
err = listen(s1, 32); err = listen(s1, 32);
if (err < 0) { if (err < 0) {
perror("listen s1 failed()\n"); perror("listen s1 failed()\n");
goto out; return errno;
} }
addr.sin_port = htons(S2_PORT); addr.sin_port = htons(S2_PORT);
err = listen(s2, 32); err = listen(s2, 32);
if (err < 0) { if (err < 0) {
perror("listen s1 failed()\n"); perror("listen s1 failed()\n");
goto out; return errno;
} }
/* Initiate Connect */ /* Initiate Connect */
...@@ -126,46 +151,56 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -126,46 +151,56 @@ static int sockmap_test_sockets(int rate, int dot)
err = connect(c1, (struct sockaddr *)&addr, sizeof(addr)); err = connect(c1, (struct sockaddr *)&addr, sizeof(addr));
if (err < 0 && errno != EINPROGRESS) { if (err < 0 && errno != EINPROGRESS) {
perror("connect c1 failed()\n"); perror("connect c1 failed()\n");
goto out; return errno;
} }
addr.sin_port = htons(S2_PORT); addr.sin_port = htons(S2_PORT);
err = connect(c2, (struct sockaddr *)&addr, sizeof(addr)); err = connect(c2, (struct sockaddr *)&addr, sizeof(addr));
if (err < 0 && errno != EINPROGRESS) { if (err < 0 && errno != EINPROGRESS) {
perror("connect c2 failed()\n"); perror("connect c2 failed()\n");
goto out; return errno;
} else if (err < 0) {
err = 0;
} }
/* Accept Connecrtions */ /* Accept Connecrtions */
p1 = accept(s1, NULL, NULL); p1 = accept(s1, NULL, NULL);
if (p1 < 0) { if (p1 < 0) {
perror("accept s1 failed()\n"); perror("accept s1 failed()\n");
goto out; return errno;
} }
p2 = accept(s2, NULL, NULL); p2 = accept(s2, NULL, NULL);
if (p2 < 0) { if (p2 < 0) {
perror("accept s1 failed()\n"); perror("accept s1 failed()\n");
goto out; return errno;
} }
max_fd = p2;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
printf("connected sockets: c1 <-> p1, c2 <-> p2\n"); printf("connected sockets: c1 <-> p1, c2 <-> p2\n");
printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n", printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n",
c1, s1, c2, s2); c1, s1, c2, s2);
return 0;
}
static int forever_ping_pong(int rate, int verbose)
{
struct timeval timeout;
char buf[1024] = {0};
int sc;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
/* Ping/Pong data from client to server */ /* Ping/Pong data from client to server */
sc = send(c1, buf, sizeof(buf), 0); sc = send(c1, buf, sizeof(buf), 0);
if (sc < 0) { if (sc < 0) {
perror("send failed()\n"); perror("send failed()\n");
goto out; return sc;
} }
do { do {
int s, rc, i; int s, rc, i, max_fd = p2;
fd_set w;
/* FD sets */ /* FD sets */
FD_ZERO(&w); FD_ZERO(&w);
...@@ -193,7 +228,7 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -193,7 +228,7 @@ static int sockmap_test_sockets(int rate, int dot)
if (rc < 0) { if (rc < 0) {
if (errno != EWOULDBLOCK) { if (errno != EWOULDBLOCK) {
perror("recv failed()\n"); perror("recv failed()\n");
break; return rc;
} }
} }
...@@ -205,35 +240,61 @@ static int sockmap_test_sockets(int rate, int dot) ...@@ -205,35 +240,61 @@ static int sockmap_test_sockets(int rate, int dot)
sc = send(i, buf, rc, 0); sc = send(i, buf, rc, 0);
if (sc < 0) { if (sc < 0) {
perror("send failed()\n"); perror("send failed()\n");
break; return sc;
} }
} }
sleep(rate);
if (dot) { if (rate)
sleep(rate);
if (verbose) {
printf("."); printf(".");
fflush(stdout); fflush(stdout);
} }
} while (running); } while (running);
out: return 0;
close(s1);
close(s2);
close(p1);
close(p2);
close(c1);
close(c2);
return err;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int rate = 1, dot = 1; int rate = 1, verbose = 0;
int opt, longindex, err, cg_fd = 0;
char filename[256]; char filename[256];
int err, cg_fd;
char *cg_path;
cg_path = argv[argc - 1]; while ((opt = getopt_long(argc, argv, "hvc:r:",
long_options, &longindex)) != -1) {
switch (opt) {
/* Cgroup configuration */
case 'c':
cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
if (cg_fd < 0) {
fprintf(stderr,
"ERROR: (%i) open cg path failed: %s\n",
cg_fd, optarg);
return cg_fd;
}
break;
case 'r':
rate = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 'h':
default:
usage(argv);
return -1;
}
}
if (!cg_fd) {
fprintf(stderr, "%s requires cgroup option: --cgroup <path>\n",
argv[0]);
return -1;
}
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
running = 1; running = 1;
...@@ -247,14 +308,6 @@ int main(int argc, char **argv) ...@@ -247,14 +308,6 @@ int main(int argc, char **argv)
return 1; return 1;
} }
/* Cgroup configuration */
cg_fd = open(cg_path, O_DIRECTORY, O_RDONLY);
if (cg_fd < 0) {
fprintf(stderr, "ERROR: (%i) open cg path failed: %s\n",
cg_fd, cg_path);
return cg_fd;
}
/* Attach programs to sockmap */ /* Attach programs to sockmap */
err = bpf_prog_attach(prog_fd[0], map_fd[0], err = bpf_prog_attach(prog_fd[0], map_fd[0],
BPF_SK_SKB_STREAM_PARSER, 0); BPF_SK_SKB_STREAM_PARSER, 0);
...@@ -280,12 +333,22 @@ int main(int argc, char **argv) ...@@ -280,12 +333,22 @@ int main(int argc, char **argv)
return err; return err;
} }
err = sockmap_test_sockets(rate, dot); err = sockmap_init_sockets();
if (err) { if (err) {
fprintf(stderr, "ERROR: test socket failed: %d\n", err); fprintf(stderr, "ERROR: test socket failed: %d\n", err);
return err; goto out;
} }
return 0;
err = forever_ping_pong(rate, verbose);
out:
close(s1);
close(s2);
close(p1);
close(p2);
close(c1);
close(c2);
close(cg_fd);
return err;
} }
void running_handler(int a) void running_handler(int a)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment