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

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
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/tcp.h> #include <linux/tcp.h>
...@@ -17,6 +18,13 @@ struct bpf_map_def SEC("maps") global_map = { ...@@ -17,6 +18,13 @@ struct bpf_map_def SEC("maps") global_map = {
.type = BPF_MAP_TYPE_ARRAY, .type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(__u32), .key_size = sizeof(__u32),
.value_size = sizeof(struct tcpbpf_globals), .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, .max_entries = 2,
}; };
...@@ -45,11 +53,14 @@ int _version SEC("version") = 1; ...@@ -45,11 +53,14 @@ int _version SEC("version") = 1;
SEC("sockops") SEC("sockops")
int bpf_testcb(struct bpf_sock_ops *skops) int bpf_testcb(struct bpf_sock_ops *skops)
{ {
int rv = -1; char header[sizeof(struct ipv6hdr) + sizeof(struct tcphdr)];
int bad_call_rv = 0; struct tcphdr *thdr;
int good_call_rv = 0; int good_call_rv = 0;
int op; int bad_call_rv = 0;
int save_syn = 1;
int rv = -1;
int v = 0; int v = 0;
int op;
op = (int) skops->op; op = (int) skops->op;
...@@ -82,6 +93,21 @@ int bpf_testcb(struct bpf_sock_ops *skops) ...@@ -82,6 +93,21 @@ int bpf_testcb(struct bpf_sock_ops *skops)
v = 0xff; v = 0xff;
rv = bpf_setsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v, rv = bpf_setsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v,
sizeof(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; break;
case BPF_SOCK_OPS_RTO_CB: case BPF_SOCK_OPS_RTO_CB:
break; break;
...@@ -111,6 +137,12 @@ int bpf_testcb(struct bpf_sock_ops *skops) ...@@ -111,6 +137,12 @@ int bpf_testcb(struct bpf_sock_ops *skops)
break; break;
case BPF_SOCK_OPS_TCP_LISTEN_CB: case BPF_SOCK_OPS_TCP_LISTEN_CB:
bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG); 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; break;
default: default:
rv = -1; rv = -1;
......
...@@ -54,6 +54,26 @@ int verify_result(const struct tcpbpf_globals *result) ...@@ -54,6 +54,26 @@ int verify_result(const struct tcpbpf_globals *result)
return -1; 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, static int bpf_find_map(const char *test, struct bpf_object *obj,
const char *name) const char *name)
{ {
...@@ -70,11 +90,11 @@ static int bpf_find_map(const char *test, struct bpf_object *obj, ...@@ -70,11 +90,11 @@ static int bpf_find_map(const char *test, struct bpf_object *obj,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const char *file = "test_tcpbpf_kern.o"; const char *file = "test_tcpbpf_kern.o";
int prog_fd, map_fd, sock_map_fd;
struct tcpbpf_globals g = {0}; struct tcpbpf_globals g = {0};
const char *cg_path = "/foo"; const char *cg_path = "/foo";
int error = EXIT_FAILURE; int error = EXIT_FAILURE;
struct bpf_object *obj; struct bpf_object *obj;
int prog_fd, map_fd;
int cg_fd = -1; int cg_fd = -1;
__u32 key = 0; __u32 key = 0;
int rv; int rv;
...@@ -110,6 +130,10 @@ int main(int argc, char **argv) ...@@ -110,6 +130,10 @@ int main(int argc, char **argv)
if (map_fd < 0) if (map_fd < 0)
goto err; 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); rv = bpf_map_lookup_elem(map_fd, &key, &g);
if (rv != 0) { if (rv != 0) {
printf("FAILED: bpf_map_lookup_elem returns %d\n", rv); printf("FAILED: bpf_map_lookup_elem returns %d\n", rv);
...@@ -121,6 +145,11 @@ int main(int argc, char **argv) ...@@ -121,6 +145,11 @@ int main(int argc, char **argv)
goto err; goto err;
} }
if (verify_sockopt_result(sock_map_fd)) {
printf("FAILED: Wrong sockopt stats\n");
goto err;
}
printf("PASSED!\n"); printf("PASSED!\n");
error = 0; error = 0;
err: err:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment