Commit 6bce9d2c authored by John Fastabend's avatar John Fastabend Committed by Daniel Borkmann

bpf: sockmap sample, add data verification option

To verify data is not being dropped or corrupted this adds an option
to verify test-patterns on recv.
Signed-off-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent e67463cb
...@@ -68,6 +68,7 @@ static const struct option long_options[] = { ...@@ -68,6 +68,7 @@ static const struct option long_options[] = {
{"iov_count", required_argument, NULL, 'i' }, {"iov_count", required_argument, NULL, 'i' },
{"length", required_argument, NULL, 'l' }, {"length", required_argument, NULL, 'l' },
{"test", required_argument, NULL, 't' }, {"test", required_argument, NULL, 't' },
{"data_test", no_argument, NULL, 'd' },
{"txmsg", no_argument, &txmsg_pass, 1 }, {"txmsg", no_argument, &txmsg_pass, 1 },
{"txmsg_noisy", no_argument, &txmsg_noisy, 1 }, {"txmsg_noisy", no_argument, &txmsg_noisy, 1 },
{"txmsg_redir", no_argument, &txmsg_redir, 1 }, {"txmsg_redir", no_argument, &txmsg_redir, 1 },
...@@ -208,45 +209,49 @@ struct msg_stats { ...@@ -208,45 +209,49 @@ struct msg_stats {
static int msg_loop_sendpage(int fd, int iov_length, int cnt, static int msg_loop_sendpage(int fd, int iov_length, int cnt,
struct msg_stats *s) struct msg_stats *s)
{ {
off_t offset = 0; unsigned char k = 0;
FILE *file; FILE *file;
int i, fp; int i, fp;
file = fopen(".sendpage_tst.tmp", "w+"); file = fopen(".sendpage_tst.tmp", "w+");
fseek(file, iov_length * cnt, SEEK_CUR); for (i = 0; i < iov_length * cnt; i++, k++)
fprintf(file, "A"); fwrite(&k, sizeof(char), 1, file);
fflush(file);
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
fclose(file);
fp = fileno(file); fp = open(".sendpage_tst.tmp", O_RDONLY);
clock_gettime(CLOCK_MONOTONIC, &s->start); clock_gettime(CLOCK_MONOTONIC, &s->start);
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
int sent = sendfile(fd, fp, &offset, iov_length); int sent = sendfile(fd, fp, NULL, iov_length);
if (sent < 0) { if (sent < 0) {
perror("send loop error:"); perror("send loop error:");
fclose(file); close(fp);
return sent; return sent;
} }
s->bytes_sent += sent; s->bytes_sent += sent;
} }
clock_gettime(CLOCK_MONOTONIC, &s->end); clock_gettime(CLOCK_MONOTONIC, &s->end);
fclose(file); close(fp);
return 0; return 0;
} }
static int msg_loop(int fd, int iov_count, int iov_length, int cnt, static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
struct msg_stats *s, bool tx) struct msg_stats *s, bool tx, bool data_test)
{ {
struct msghdr msg = {0}; struct msghdr msg = {0};
int err, i, flags = MSG_NOSIGNAL; int err, i, flags = MSG_NOSIGNAL;
struct iovec *iov; struct iovec *iov;
unsigned char k;
iov = calloc(iov_count, sizeof(struct iovec)); iov = calloc(iov_count, sizeof(struct iovec));
if (!iov) if (!iov)
return errno; return errno;
k = 0;
for (i = 0; i < iov_count; i++) { for (i = 0; i < iov_count; i++) {
char *d = calloc(iov_length, sizeof(char)); unsigned char *d = calloc(iov_length, sizeof(char));
if (!d) { if (!d) {
fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count); fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
...@@ -254,10 +259,18 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, ...@@ -254,10 +259,18 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
} }
iov[i].iov_base = d; iov[i].iov_base = d;
iov[i].iov_len = iov_length; iov[i].iov_len = iov_length;
if (data_test && tx) {
int j;
for (j = 0; j < iov_length; j++)
d[j] = k++;
}
} }
msg.msg_iov = iov; msg.msg_iov = iov;
msg.msg_iovlen = iov_count; msg.msg_iovlen = iov_count;
k = 0;
if (tx) { if (tx) {
clock_gettime(CLOCK_MONOTONIC, &s->start); clock_gettime(CLOCK_MONOTONIC, &s->start);
...@@ -311,6 +324,26 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, ...@@ -311,6 +324,26 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
} }
s->bytes_recvd += recv; s->bytes_recvd += recv;
if (data_test) {
int j;
for (i = 0; i < msg.msg_iovlen; i++) {
unsigned char *d = iov[i].iov_base;
for (j = 0;
j < iov[i].iov_len && recv; j++) {
if (d[j] != k++) {
errno = -EIO;
fprintf(stderr,
"detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
i, j, d[j], k - 1, d[j+1], k + 1);
goto out_errno;
}
recv--;
}
}
}
} }
clock_gettime(CLOCK_MONOTONIC, &s->end); clock_gettime(CLOCK_MONOTONIC, &s->end);
} }
...@@ -338,8 +371,15 @@ static inline float recvdBps(struct msg_stats s) ...@@ -338,8 +371,15 @@ static inline float recvdBps(struct msg_stats s)
return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec); return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec);
} }
struct sockmap_options {
int verbose;
bool base;
bool sendpage;
bool data_test;
};
static int sendmsg_test(int iov_count, int iov_buf, int cnt, static int sendmsg_test(int iov_count, int iov_buf, int cnt,
int verbose, bool base, bool sendpage) struct sockmap_options *opt)
{ {
float sent_Bps = 0, recvd_Bps = 0; float sent_Bps = 0, recvd_Bps = 0;
int rx_fd, txpid, rxpid, err = 0; int rx_fd, txpid, rxpid, err = 0;
...@@ -348,16 +388,17 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt, ...@@ -348,16 +388,17 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,
errno = 0; errno = 0;
if (base) if (opt->base)
rx_fd = p1; rx_fd = p1;
else else
rx_fd = p2; rx_fd = p2;
rxpid = fork(); rxpid = fork();
if (rxpid == 0) { if (rxpid == 0) {
if (sendpage) if (opt->sendpage)
iov_count = 1; iov_count = 1;
err = msg_loop(rx_fd, iov_count, iov_buf, cnt, &s, false); err = msg_loop(rx_fd, iov_count, iov_buf,
cnt, &s, false, opt->data_test);
if (err) if (err)
fprintf(stderr, fprintf(stderr,
"msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n", "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
...@@ -380,10 +421,11 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt, ...@@ -380,10 +421,11 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,
txpid = fork(); txpid = fork();
if (txpid == 0) { if (txpid == 0) {
if (sendpage) if (opt->sendpage)
err = msg_loop_sendpage(c1, iov_buf, cnt, &s); err = msg_loop_sendpage(c1, iov_buf, cnt, &s);
else else
err = msg_loop(c1, iov_count, iov_buf, cnt, &s, true); err = msg_loop(c1, iov_count, iov_buf,
cnt, &s, true, opt->data_test);
if (err) if (err)
fprintf(stderr, fprintf(stderr,
...@@ -409,7 +451,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt, ...@@ -409,7 +451,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,
return err; return err;
} }
static int forever_ping_pong(int rate, int verbose) static int forever_ping_pong(int rate, struct sockmap_options *opt)
{ {
struct timeval timeout; struct timeval timeout;
char buf[1024] = {0}; char buf[1024] = {0};
...@@ -474,7 +516,7 @@ static int forever_ping_pong(int rate, int verbose) ...@@ -474,7 +516,7 @@ static int forever_ping_pong(int rate, int verbose)
if (rate) if (rate)
sleep(rate); sleep(rate);
if (verbose) { if (opt->verbose) {
printf("."); printf(".");
fflush(stdout); fflush(stdout);
...@@ -494,13 +536,14 @@ enum { ...@@ -494,13 +536,14 @@ enum {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int iov_count = 1, length = 1024, rate = 1, verbose = 0, tx_prog_fd; int iov_count = 1, length = 1024, rate = 1, tx_prog_fd;
struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY}; struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
int opt, longindex, err, cg_fd = 0; int opt, longindex, err, cg_fd = 0;
struct sockmap_options options = {0};
int test = PING_PONG; int test = PING_PONG;
char filename[256]; char filename[256];
while ((opt = getopt_long(argc, argv, ":hvc:r:i:l:t:", while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:",
long_options, &longindex)) != -1) { long_options, &longindex)) != -1) {
switch (opt) { switch (opt) {
/* Cgroup configuration */ /* Cgroup configuration */
...@@ -517,7 +560,7 @@ int main(int argc, char **argv) ...@@ -517,7 +560,7 @@ int main(int argc, char **argv)
rate = atoi(optarg); rate = atoi(optarg);
break; break;
case 'v': case 'v':
verbose = 1; options.verbose = 1;
break; break;
case 'i': case 'i':
iov_count = atoi(optarg); iov_count = atoi(optarg);
...@@ -525,6 +568,9 @@ int main(int argc, char **argv) ...@@ -525,6 +568,9 @@ int main(int argc, char **argv)
case 'l': case 'l':
length = atoi(optarg); length = atoi(optarg);
break; break;
case 'd':
options.data_test = true;
break;
case 't': case 't':
if (strcmp(optarg, "ping") == 0) { if (strcmp(optarg, "ping") == 0) {
test = PING_PONG; test = PING_PONG;
...@@ -655,20 +701,24 @@ int main(int argc, char **argv) ...@@ -655,20 +701,24 @@ int main(int argc, char **argv)
} }
} }
if (test == PING_PONG) if (test == PING_PONG)
err = forever_ping_pong(rate, verbose); err = forever_ping_pong(rate, &options);
else if (test == SENDMSG) else if (test == SENDMSG) {
err = sendmsg_test(iov_count, length, rate, options.base = false;
verbose, false, false); options.sendpage = false;
else if (test == SENDPAGE) err = sendmsg_test(iov_count, length, rate, &options);
err = sendmsg_test(iov_count, length, rate, } else if (test == SENDPAGE) {
verbose, false, true); options.base = false;
else if (test == BASE) options.sendpage = true;
err = sendmsg_test(iov_count, length, rate, err = sendmsg_test(iov_count, length, rate, &options);
verbose, true, false); } else if (test == BASE) {
else if (test == BASE_SENDPAGE) options.base = true;
err = sendmsg_test(iov_count, length, rate, options.sendpage = false;
verbose, true, true); err = sendmsg_test(iov_count, length, rate, &options);
else } else if (test == BASE_SENDPAGE) {
options.base = true;
options.sendpage = true;
err = sendmsg_test(iov_count, length, rate, &options);
} else
fprintf(stderr, "unknown test\n"); fprintf(stderr, "unknown test\n");
out: out:
bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS); bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS);
......
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