bpf: sockmap sample, add option to attach SK_MSG program
Add sockmap option to use SK_MSG program types. 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>
This commit is contained in:
parent
1acc60b6a4
commit
4c4c3c276c
|
@ -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_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0;
|
||||||
bool is_sockops = strncmp(event, "sockops", 7) == 0;
|
bool is_sockops = strncmp(event, "sockops", 7) == 0;
|
||||||
bool is_sk_skb = strncmp(event, "sk_skb", 6) == 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);
|
size_t insns_cnt = size / sizeof(struct bpf_insn);
|
||||||
enum bpf_prog_type prog_type;
|
enum bpf_prog_type prog_type;
|
||||||
char buf[256];
|
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;
|
prog_type = BPF_PROG_TYPE_SOCK_OPS;
|
||||||
} else if (is_sk_skb) {
|
} else if (is_sk_skb) {
|
||||||
prog_type = BPF_PROG_TYPE_SK_SKB;
|
prog_type = BPF_PROG_TYPE_SK_SKB;
|
||||||
|
} else if (is_sk_msg) {
|
||||||
|
prog_type = BPF_PROG_TYPE_SK_MSG;
|
||||||
} else {
|
} else {
|
||||||
printf("Unknown event '%s'\n", event);
|
printf("Unknown event '%s'\n", event);
|
||||||
return -1;
|
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)
|
if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (is_socket || is_sockops || is_sk_skb) {
|
if (is_socket || is_sockops || is_sk_skb || is_sk_msg) {
|
||||||
if (is_socket)
|
if (is_socket)
|
||||||
event += 6;
|
event += 6;
|
||||||
else
|
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, "socket", 6) == 0 ||
|
||||||
memcmp(shname, "cgroup/", 7) == 0 ||
|
memcmp(shname, "cgroup/", 7) == 0 ||
|
||||||
memcmp(shname, "sockops", 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,
|
ret = load_and_attach(shname, data->d_buf,
|
||||||
data->d_size);
|
data->d_size);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
|
|
|
@ -43,6 +43,20 @@ struct bpf_map_def SEC("maps") sock_map = {
|
||||||
.max_entries = 20,
|
.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")
|
SEC("sk_skb1")
|
||||||
int bpf_prog1(struct __sk_buff *skb)
|
int bpf_prog1(struct __sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
@ -105,4 +119,42 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
|
||||||
|
|
||||||
return 0;
|
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";
|
char _license[] SEC("license") = "GPL";
|
||||||
|
|
|
@ -54,6 +54,11 @@ void running_handler(int a);
|
||||||
/* global sockets */
|
/* global sockets */
|
||||||
int s1, s2, c1, c2, p1, p2;
|
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[] = {
|
static const struct option long_options[] = {
|
||||||
{"help", no_argument, NULL, 'h' },
|
{"help", no_argument, NULL, 'h' },
|
||||||
{"cgroup", required_argument, NULL, 'c' },
|
{"cgroup", required_argument, NULL, 'c' },
|
||||||
|
@ -62,6 +67,10 @@ static const struct option long_options[] = {
|
||||||
{"iov_count", required_argument, NULL, 'i' },
|
{"iov_count", required_argument, NULL, 'i' },
|
||||||
{"length", required_argument, NULL, 'l' },
|
{"length", required_argument, NULL, 'l' },
|
||||||
{"test", required_argument, NULL, 't' },
|
{"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 }
|
{0, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -447,13 +456,13 @@ enum {
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
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};
|
struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
|
||||||
int opt, longindex, err, cg_fd = 0;
|
int opt, longindex, err, cg_fd = 0;
|
||||||
int test = PING_PONG;
|
int test = PING_PONG;
|
||||||
char filename[256];
|
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) {
|
long_options, &longindex)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
/* Cgroup configuration */
|
/* Cgroup configuration */
|
||||||
|
@ -490,6 +499,8 @@ int main(int argc, char **argv)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
usage(argv);
|
usage(argv);
|
||||||
|
@ -515,16 +526,16 @@ int main(int argc, char **argv)
|
||||||
/* catch SIGINT */
|
/* catch SIGINT */
|
||||||
signal(SIGINT, running_handler);
|
signal(SIGINT, running_handler);
|
||||||
|
|
||||||
/* If base test skip BPF setup */
|
|
||||||
if (test == BASE)
|
|
||||||
goto run;
|
|
||||||
|
|
||||||
if (load_bpf_file(filename)) {
|
if (load_bpf_file(filename)) {
|
||||||
fprintf(stderr, "load_bpf_file: (%s) %s\n",
|
fprintf(stderr, "load_bpf_file: (%s) %s\n",
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If base test skip BPF setup */
|
||||||
|
if (test == BASE)
|
||||||
|
goto run;
|
||||||
|
|
||||||
/* Attach programs to sockmap */
|
/* Attach programs to sockmap */
|
||||||
err = bpf_prog_attach(prog_fd[0], map_fd[0],
|
err = bpf_prog_attach(prog_fd[0], map_fd[0],
|
||||||
BPF_SK_SKB_STREAM_PARSER, 0);
|
BPF_SK_SKB_STREAM_PARSER, 0);
|
||||||
|
@ -557,6 +568,50 @@ run:
|
||||||
goto out;
|
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)
|
if (test == PING_PONG)
|
||||||
err = forever_ping_pong(rate, verbose);
|
err = forever_ping_pong(rate, verbose);
|
||||||
else if (test == SENDMSG)
|
else if (test == SENDMSG)
|
||||||
|
|
|
@ -720,6 +720,15 @@ union bpf_attr {
|
||||||
* int bpf_override_return(pt_regs, rc)
|
* int bpf_override_return(pt_regs, rc)
|
||||||
* @pt_regs: pointer to struct pt_regs
|
* @pt_regs: pointer to struct pt_regs
|
||||||
* @rc: the return value to set
|
* @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) \
|
#define __BPF_FUNC_MAPPER(FN) \
|
||||||
FN(unspec), \
|
FN(unspec), \
|
||||||
|
@ -781,7 +790,9 @@ union bpf_attr {
|
||||||
FN(perf_prog_read_value), \
|
FN(perf_prog_read_value), \
|
||||||
FN(getsockopt), \
|
FN(getsockopt), \
|
||||||
FN(override_return), \
|
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
|
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||||
* function eBPF program intends to call
|
* function eBPF program intends to call
|
||||||
|
|
|
@ -1857,6 +1857,7 @@ static const struct {
|
||||||
BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT),
|
BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT),
|
||||||
BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS),
|
BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS),
|
||||||
BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB),
|
BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB),
|
||||||
|
BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG),
|
||||||
};
|
};
|
||||||
#undef BPF_PROG_SEC
|
#undef BPF_PROG_SEC
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,9 @@ static int (*bpf_perf_prog_read_value)(void *ctx, void *buf,
|
||||||
(void *) BPF_FUNC_perf_prog_read_value;
|
(void *) BPF_FUNC_perf_prog_read_value;
|
||||||
static int (*bpf_override_return)(void *ctx, unsigned long rc) =
|
static int (*bpf_override_return)(void *ctx, unsigned long rc) =
|
||||||
(void *) BPF_FUNC_override_return;
|
(void *) BPF_FUNC_override_return;
|
||||||
|
static int (*bpf_msg_redirect_map)(void *ctx, void *map, int key, int flags) =
|
||||||
|
(void *) BPF_FUNC_msg_redirect_map;
|
||||||
|
|
||||||
|
|
||||||
/* llvm builtin functions that eBPF C program may use to
|
/* llvm builtin functions that eBPF C program may use to
|
||||||
* emit BPF_LD_ABS and BPF_LD_IND instructions
|
* emit BPF_LD_ABS and BPF_LD_IND instructions
|
||||||
|
|
Loading…
Reference in a new issue