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

Commit 4c4c3c27 authored by John Fastabend's avatar John Fastabend Committed by Daniel Borkmann
Browse files

bpf: sockmap sample, add option to attach SK_MSG program



Add sockmap option to use SK_MSG program types.

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 1acc60b6
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
	bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0;
	bool is_sockops = strncmp(event, "sockops", 7) == 0;
	bool is_sk_skb = strncmp(event, "sk_skb", 6) == 0;
	bool is_sk_msg = strncmp(event, "sk_msg", 6) == 0;
	size_t insns_cnt = size / sizeof(struct bpf_insn);
	enum bpf_prog_type prog_type;
	char buf[256];
@@ -96,6 +97,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
		prog_type = BPF_PROG_TYPE_SOCK_OPS;
	} else if (is_sk_skb) {
		prog_type = BPF_PROG_TYPE_SK_SKB;
	} else if (is_sk_msg) {
		prog_type = BPF_PROG_TYPE_SK_MSG;
	} else {
		printf("Unknown event '%s'\n", event);
		return -1;
@@ -113,7 +116,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
	if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk)
		return 0;

	if (is_socket || is_sockops || is_sk_skb) {
	if (is_socket || is_sockops || is_sk_skb || is_sk_msg) {
		if (is_socket)
			event += 6;
		else
@@ -589,7 +592,8 @@ static int do_load_bpf_file(const char *path, fixup_map_cb fixup_map)
		    memcmp(shname, "socket", 6) == 0 ||
		    memcmp(shname, "cgroup/", 7) == 0 ||
		    memcmp(shname, "sockops", 7) == 0 ||
		    memcmp(shname, "sk_skb", 6) == 0) {
		    memcmp(shname, "sk_skb", 6) == 0 ||
		    memcmp(shname, "sk_msg", 6) == 0) {
			ret = load_and_attach(shname, data->d_buf,
					      data->d_size);
			if (ret != 0)
+52 −0
Original line number Diff line number Diff line
@@ -43,6 +43,20 @@ struct bpf_map_def SEC("maps") sock_map = {
	.max_entries = 20,
};

struct bpf_map_def SEC("maps") sock_map_txmsg = {
	.type = BPF_MAP_TYPE_SOCKMAP,
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.max_entries = 20,
};

struct bpf_map_def SEC("maps") sock_map_redir = {
	.type = BPF_MAP_TYPE_SOCKMAP,
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.max_entries = 1,
};

SEC("sk_skb1")
int bpf_prog1(struct __sk_buff *skb)
{
@@ -105,4 +119,42 @@ int bpf_sockmap(struct bpf_sock_ops *skops)

	return 0;
}

SEC("sk_msg1")
int bpf_prog4(struct sk_msg_md *msg)
{
	return SK_PASS;
}

SEC("sk_msg2")
int bpf_prog5(struct sk_msg_md *msg)
{
	void *data_end = (void *)(long) msg->data_end;
	void *data = (void *)(long) msg->data;

	bpf_printk("sk_msg2: data length %i\n", (__u32)data_end - (__u32)data);
	return SK_PASS;
}

SEC("sk_msg3")
int bpf_prog6(struct sk_msg_md *msg)
{
	void *data_end = (void *)(long) msg->data_end;
	void *data = (void *)(long) msg->data;
	int ret = 0;

	return bpf_msg_redirect_map(msg, &sock_map_redir, ret, 0);
}

SEC("sk_msg4")
int bpf_prog7(struct sk_msg_md *msg)
{
	void *data_end = (void *)(long) msg->data_end;
	void *data = (void *)(long) msg->data;
	int ret = 0;

	bpf_printk("sk_msg3: redirect(%iB)\n", (__u32)data_end - (__u32)data);
	return bpf_msg_redirect_map(msg, &sock_map_redir, ret, 0);
}

char _license[] SEC("license") = "GPL";
+61 −6
Original line number Diff line number Diff line
@@ -54,6 +54,11 @@ void running_handler(int a);
/* global sockets */
int s1, s2, c1, c2, p1, p2;

int txmsg_pass;
int txmsg_noisy;
int txmsg_redir;
int txmsg_redir_noisy;

static const struct option long_options[] = {
	{"help",	no_argument,		NULL, 'h' },
	{"cgroup",	required_argument,	NULL, 'c' },
@@ -62,6 +67,10 @@ static const struct option long_options[] = {
	{"iov_count",	required_argument,	NULL, 'i' },
	{"length",	required_argument,	NULL, 'l' },
	{"test",	required_argument,	NULL, 't' },
	{"txmsg",		no_argument,		&txmsg_pass,  1  },
	{"txmsg_noisy",		no_argument,		&txmsg_noisy, 1  },
	{"txmsg_redir",		no_argument,		&txmsg_redir, 1  },
	{"txmsg_redir_noisy",	no_argument,		&txmsg_redir_noisy, 1},
	{0, 0, NULL, 0 }
};

@@ -447,13 +456,13 @@ enum {

int main(int argc, char **argv)
{
	int iov_count = 1, length = 1024, rate = 1, verbose = 0;
	int iov_count = 1, length = 1024, rate = 1, verbose = 0, tx_prog_fd;
	struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
	int opt, longindex, err, cg_fd = 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, ":hvc:r:i:l:t:",
				  long_options, &longindex)) != -1) {
		switch (opt) {
		/* Cgroup configuration */
@@ -490,6 +499,8 @@ int main(int argc, char **argv)
				return -1;
			}
			break;
		case 0:
			break;
		case 'h':
		default:
			usage(argv);
@@ -515,16 +526,16 @@ int main(int argc, char **argv)
	/* catch SIGINT */
	signal(SIGINT, running_handler);

	/* If base test skip BPF setup */
	if (test == BASE)
		goto run;

	if (load_bpf_file(filename)) {
		fprintf(stderr, "load_bpf_file: (%s) %s\n",
			filename, strerror(errno));
		return 1;
	}

	/* If base test skip BPF setup */
	if (test == BASE)
		goto run;

	/* Attach programs to sockmap */
	err = bpf_prog_attach(prog_fd[0], map_fd[0],
				BPF_SK_SKB_STREAM_PARSER, 0);
@@ -557,6 +568,50 @@ int main(int argc, char **argv)
		goto out;
	}

	/* Attach txmsg program to sockmap */
	if (txmsg_pass)
		tx_prog_fd = prog_fd[3];
	else if (txmsg_noisy)
		tx_prog_fd = prog_fd[4];
	else if (txmsg_redir)
		tx_prog_fd = prog_fd[5];
	else if (txmsg_redir_noisy)
		tx_prog_fd = prog_fd[6];
	else
		tx_prog_fd = 0;

	if (tx_prog_fd) {
		int redir_fd, i = 0;

		err = bpf_prog_attach(tx_prog_fd,
				      map_fd[1], BPF_SK_MSG_VERDICT, 0);
		if (err) {
			fprintf(stderr,
				"ERROR: bpf_prog_attach (txmsg): %d (%s)\n",
				err, strerror(errno));
			return err;
		}

		err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY);
		if (err) {
			fprintf(stderr,
				"ERROR: bpf_map_update_elem (txmsg):  %d (%s\n",
				err, strerror(errno));
			return err;
		}
		if (test == SENDMSG)
			redir_fd = c2;
		else
			redir_fd = c1;

		err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY);
		if (err) {
			fprintf(stderr,
				"ERROR: bpf_map_update_elem (txmsg):  %d (%s\n",
				err, strerror(errno));
			return err;
		}
	}
	if (test == PING_PONG)
		err = forever_ping_pong(rate, verbose);
	else if (test == SENDMSG)
+12 −1
Original line number Diff line number Diff line
@@ -720,6 +720,15 @@ union bpf_attr {
 * int bpf_override_return(pt_regs, rc)
 *	@pt_regs: pointer to struct pt_regs
 *	@rc: the return value to set
 *
 * int bpf_msg_redirect_map(map, key, flags)
 *     Redirect msg to a sock in map using key as a lookup key for the
 *     sock in map.
 *     @map: pointer to sockmap
 *     @key: key to lookup sock in map
 *     @flags: reserved for future use
 *     Return: SK_PASS
 *
 */
#define __BPF_FUNC_MAPPER(FN)		\
	FN(unspec),			\
@@ -781,7 +790,9 @@ union bpf_attr {
	FN(perf_prog_read_value),	\
	FN(getsockopt),			\
	FN(override_return),		\
	FN(sock_ops_cb_flags_set),
	FN(sock_ops_cb_flags_set),	\
	FN(msg_redirect_map),		\
	FN(msg_apply_bytes),

/* integer value in 'imm' field of BPF_CALL instruction selects which helper
 * function eBPF program intends to call
+1 −0
Original line number Diff line number Diff line
@@ -1857,6 +1857,7 @@ static const struct {
	BPF_PROG_SEC("lwt_xmit",	BPF_PROG_TYPE_LWT_XMIT),
	BPF_PROG_SEC("sockops",		BPF_PROG_TYPE_SOCK_OPS),
	BPF_PROG_SEC("sk_skb",		BPF_PROG_TYPE_SK_SKB),
	BPF_PROG_SEC("sk_msg",		BPF_PROG_TYPE_SK_MSG),
};
#undef BPF_PROG_SEC

Loading