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

Commit 9746b1ee authored by Nikita V. Shirokov's avatar Nikita V. Shirokov Committed by Daniel Borkmann
Browse files

bpf: add selftest for bpf's (set|get)_sockopt for SAVE_SYN



adding selftest for feature, introduced in commit 9452048c79404 ("bpf:
add TCP_SAVE_SYN/TCP_SAVED_SYN options for bpf_(set|get)sockopt").

Signed-off-by: default avatarNikita V. Shirokov <tehnerd@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 11c3f511
Loading
Loading
Loading
Loading
+35 −3
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/tcp.h>
@@ -17,6 +18,13 @@ struct bpf_map_def SEC("maps") global_map = {
	.type = BPF_MAP_TYPE_ARRAY,
	.key_size = sizeof(__u32),
	.value_size = sizeof(struct tcpbpf_globals),
	.max_entries = 4,
};

struct bpf_map_def SEC("maps") sockopt_results = {
	.type = BPF_MAP_TYPE_ARRAY,
	.key_size = sizeof(__u32),
	.value_size = sizeof(int),
	.max_entries = 2,
};

@@ -45,11 +53,14 @@ int _version SEC("version") = 1;
SEC("sockops")
int bpf_testcb(struct bpf_sock_ops *skops)
{
	int rv = -1;
	int bad_call_rv = 0;
	char header[sizeof(struct ipv6hdr) + sizeof(struct tcphdr)];
	struct tcphdr *thdr;
	int good_call_rv = 0;
	int op;
	int bad_call_rv = 0;
	int save_syn = 1;
	int rv = -1;
	int v = 0;
	int op;

	op = (int) skops->op;

@@ -82,6 +93,21 @@ int bpf_testcb(struct bpf_sock_ops *skops)
		v = 0xff;
		rv = bpf_setsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v,
				    sizeof(v));
		if (skops->family == AF_INET6) {
			v = bpf_getsockopt(skops, IPPROTO_TCP, TCP_SAVED_SYN,
					   header, (sizeof(struct ipv6hdr) +
						    sizeof(struct tcphdr)));
			if (!v) {
				int offset = sizeof(struct ipv6hdr);

				thdr = (struct tcphdr *)(header + offset);
				v = thdr->syn;
				__u32 key = 1;

				bpf_map_update_elem(&sockopt_results, &key, &v,
						    BPF_ANY);
			}
		}
		break;
	case BPF_SOCK_OPS_RTO_CB:
		break;
@@ -111,6 +137,12 @@ int bpf_testcb(struct bpf_sock_ops *skops)
		break;
	case BPF_SOCK_OPS_TCP_LISTEN_CB:
		bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG);
		v = bpf_setsockopt(skops, IPPROTO_TCP, TCP_SAVE_SYN,
				   &save_syn, sizeof(save_syn));
		/* Update global map w/ result of setsock opt */
		__u32 key = 0;

		bpf_map_update_elem(&sockopt_results, &key, &v, BPF_ANY);
		break;
	default:
		rv = -1;
+30 −1
Original line number Diff line number Diff line
@@ -54,6 +54,26 @@ int verify_result(const struct tcpbpf_globals *result)
	return -1;
}

int verify_sockopt_result(int sock_map_fd)
{
	__u32 key = 0;
	int res;
	int rv;

	/* check setsockopt for SAVE_SYN */
	rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
	EXPECT_EQ(0, rv, "d");
	EXPECT_EQ(0, res, "d");
	key = 1;
	/* check getsockopt for SAVED_SYN */
	rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
	EXPECT_EQ(0, rv, "d");
	EXPECT_EQ(1, res, "d");
	return 0;
err:
	return -1;
}

static int bpf_find_map(const char *test, struct bpf_object *obj,
			const char *name)
{
@@ -70,11 +90,11 @@ static int bpf_find_map(const char *test, struct bpf_object *obj,
int main(int argc, char **argv)
{
	const char *file = "test_tcpbpf_kern.o";
	int prog_fd, map_fd, sock_map_fd;
	struct tcpbpf_globals g = {0};
	const char *cg_path = "/foo";
	int error = EXIT_FAILURE;
	struct bpf_object *obj;
	int prog_fd, map_fd;
	int cg_fd = -1;
	__u32 key = 0;
	int rv;
@@ -110,6 +130,10 @@ int main(int argc, char **argv)
	if (map_fd < 0)
		goto err;

	sock_map_fd = bpf_find_map(__func__, obj, "sockopt_results");
	if (sock_map_fd < 0)
		goto err;

	rv = bpf_map_lookup_elem(map_fd, &key, &g);
	if (rv != 0) {
		printf("FAILED: bpf_map_lookup_elem returns %d\n", rv);
@@ -121,6 +145,11 @@ int main(int argc, char **argv)
		goto err;
	}

	if (verify_sockopt_result(sock_map_fd)) {
		printf("FAILED: Wrong sockopt stats\n");
		goto err;
	}

	printf("PASSED!\n");
	error = 0;
err: