[bpf-next PATCH 12/16] bpf: sockmap sample, add data verification option

John Fastabend
2018-03-05T19:52:02Z

To verify data is not being dropped or corrupted this adds an option
to verify test-patterns on recv.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
samples/sockmap/sockmap_user.c | 118 ++++++++++++++++++++++++++++------------
1 file changed, 84 insertions(+), 34 deletions(-)

diff --git a/samples/sockmap/sockmap_user.c b/samples/sockmap/sockmap_user.c
index ec624a8..8017ad7a 100644
--- a/samples/sockmap/sockmap_user.c
+++ b/samples/sockmap/sockmap_user.c
@@ -68,6 +68,7 @@
{"iov_count", required_argument, NULL, 'i' },
{"length", required_argument, NULL, 'l' },
{"test", required_argument, NULL, 't' },
+ {"data_test", no_argument, NULL, 'd' },
{"txmsg", no_argument, &txmsg_pass, 1 },
{"txmsg_noisy", no_argument, &txmsg_noisy, 1 },
{"txmsg_redir", no_argument, &txmsg_redir, 1 },
@@ -208,45 +209,49 @@ struct msg_stats {
static int msg_loop_sendpage(int fd, int iov_length, int cnt,
struct msg_stats *s)
{
- off_t offset = 0;
+ unsigned char k = 0;
FILE *file;
int i, fp;

file = fopen(".sendpage_tst.tmp", "w+");
- fseek(file, iov_length * cnt, SEEK_CUR);
- fprintf(file, "A");
+ for (i = 0; i < iov_length * cnt; i++, k++)
+ fwrite(&k, sizeof(char), 1, file);
+ fflush(file);
fseek(file, 0, SEEK_SET);
+ fclose(file);

- fp = fileno(file);
+ fp = open(".sendpage_tst.tmp", O_RDONLY);
clock_gettime(CLOCK_MONOTONIC, &s->start);
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) {
perror("send loop error:");
- fclose(file);
+ close(fp);
return sent;
}
s->bytes_sent += sent;
}
clock_gettime(CLOCK_MONOTONIC, &s->end);
- fclose(file);
+ close(fp);
return 0;
}

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};
int err, i, flags = MSG_NOSIGNAL;
struct iovec *iov;
+ unsigned char k;

iov = calloc(iov_count, sizeof(struct iovec));
if (!iov)
return errno;

+ k = 0;
for (i = 0; i < iov_count; i++) {
- char *d = calloc(iov_length, sizeof(char));
+ unsigned char *d = calloc(iov_length, sizeof(char));

if (!d) {
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,
}
iov[i].iov_base = d;
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_iovlen = iov_count;
+ k = 0;

if (tx) {
clock_gettime(CLOCK_MONOTONIC, &s->start);
@@ -311,6 +324,26 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
}

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);
}
@@ -338,8 +371,15 @@ static inline float recvdBps(struct msg_stats s)
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,
- int verbose, bool base, bool sendpage)
+ struct sockmap_options *opt)
{
float sent_Bps = 0, recvd_Bps = 0;
int rx_fd, txpid, rxpid, err = 0;
@@ -348,16 +388,17 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,

errno = 0;

- if (base)
+ if (opt->base)
rx_fd = p1;
else
rx_fd = p2;

rxpid = fork();
if (rxpid == 0) {
- if (sendpage)
+ if (opt->sendpage)
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)
fprintf(stderr,
"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,

txpid = fork();
if (txpid == 0) {
- if (sendpage)
+ if (opt->sendpage)
err = msg_loop_sendpage(c1, iov_buf, cnt, &s);
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)
fprintf(stderr,
@@ -409,7 +451,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,
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;
char buf[1024] = {0};
@@ -474,7 +516,7 @@ static int forever_ping_pong(int rate, int verbose)
if (rate)
sleep(rate);

- if (verbose) {
+ if (opt->verbose) {
printf(".");
fflush(stdout);

@@ -494,13 +536,14 @@ enum {

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};
int opt, longindex, err, cg_fd = 0;
+ struct sockmap_options options = {0};
int test = PING_PONG;
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) {
switch (opt) {
/* Cgroup configuration */
@@ -517,7 +560,7 @@ int main(int argc, char **argv)
rate = atoi(optarg);
break;
case 'v':
- verbose = 1;
+ options.verbose = 1;
break;
case 'i':
iov_count = atoi(optarg);
@@ -525,6 +568,9 @@ int main(int argc, char **argv)
case 'l':
length = atoi(optarg);
break;
+ case 'd':
+ options.data_test = true;
+ break;
case 't':
if (strcmp(optarg, "ping") == 0) {
test = PING_PONG;
@@ -655,20 +701,24 @@ int main(int argc, char **argv)
}
}
if (test == PING_PONG)
- err = forever_ping_pong(rate, verbose);
- else if (test == SENDMSG)
- err = sendmsg_test(iov_count, length, rate,
- verbose, false, false);
- else if (test == SENDPAGE)
- err = sendmsg_test(iov_count, length, rate,
- verbose, false, true);
- else if (test == BASE)
- err = sendmsg_test(iov_count, length, rate,
- verbose, true, false);
- else if (test == BASE_SENDPAGE)
- err = sendmsg_test(iov_count, length, rate,
- verbose, true, true);
- else
+ err = forever_ping_pong(rate, &options);
+ else if (test == SENDMSG) {
+ options.base = false;
+ options.sendpage = false;
+ err = sendmsg_test(iov_count, length, rate, &options);
+ } else if (test == SENDPAGE) {
+ options.base = false;
+ options.sendpage = true;
+ err = sendmsg_test(iov_count, length, rate, &options);
+ } else if (test == BASE) {
+ options.base = true;
+ options.sendpage = false;
+ err = sendmsg_test(iov_count, length, rate, &options);
+ } 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");
out:
bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS);