Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+84 −34
Original line number Diff line number Diff line
@@ -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  },
@@ -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);