Skip to content

Commit

Permalink
bpf: sockmap sample, add data verification option
Browse files Browse the repository at this point in the history
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>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
  • Loading branch information
John Fastabend authored and Daniel Borkmann committed Mar 19, 2018
1 parent e67463c commit 6bce9d2
Showing 1 changed file with 84 additions and 34 deletions.
118 changes: 84 additions & 34 deletions samples/sockmap/sockmap_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ static const struct option long_options[] = {
{"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 },
Expand Down Expand Up @@ -208,56 +209,68 @@ 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);
goto out_errno;
}
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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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",
Expand All @@ -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,
Expand All @@ -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};
Expand Down Expand Up @@ -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);

Expand All @@ -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 */
Expand All @@ -517,14 +560,17 @@ int main(int argc, char **argv)
rate = atoi(optarg);
break;
case 'v':
verbose = 1;
options.verbose = 1;
break;
case 'i':
iov_count = atoi(optarg);
break;
case 'l':
length = atoi(optarg);
break;
case 'd':
options.data_test = true;
break;
case 't':
if (strcmp(optarg, "ping") == 0) {
test = PING_PONG;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 6bce9d2

Please sign in to comment.