Skip to content

Commit 0b9ad56

Browse files
jsitnickiborkmann
authored andcommitted
selftests/bpf: Use SOCKMAP for server sockets in bpf_sk_assign test
Update bpf_sk_assign test to fetch the server socket from SOCKMAP, now that map lookup from BPF in SOCKMAP is enabled. This way the test TC BPF program doesn't need to know what address server socket is bound to. Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20200429181154.479310-4-jakub@cloudflare.com
1 parent 34a2cc6 commit 0b9ad56

File tree

3 files changed

+53
-52
lines changed

3 files changed

+53
-52
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ define GCC_BPF_BUILD_RULE
243243
$(BPF_GCC) $3 $4 -O2 -c $1 -o $2
244244
endef
245245

246-
SKEL_BLACKLIST := btf__% test_pinning_invalid.c
246+
SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
247247

248248
# Set up extra TRUNNER_XXX "temporary" variables in the environment (relies on
249249
# $eval()) and pass control to DEFINE_TEST_RUNNER_RULES.

tools/testing/selftests/bpf/prog_tests/sk_assign.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define CONNECT_PORT 4321
2121
#define TEST_DADDR (0xC0A80203)
2222
#define NS_SELF "/proc/self/ns/net"
23+
#define SERVER_MAP_PATH "/sys/fs/bpf/tc/globals/server_map"
2324

2425
static const struct timeval timeo_sec = { .tv_sec = 3 };
2526
static const size_t timeo_optlen = sizeof(timeo_sec);
@@ -265,6 +266,7 @@ void test_sk_assign(void)
265266
TEST("ipv6 udp addr redir", AF_INET6, SOCK_DGRAM, true),
266267
};
267268
int server = -1;
269+
int server_map;
268270
int self_net;
269271

270272
self_net = open(NS_SELF, O_RDONLY);
@@ -278,17 +280,31 @@ void test_sk_assign(void)
278280
goto cleanup;
279281
}
280282

283+
server_map = bpf_obj_get(SERVER_MAP_PATH);
284+
if (CHECK_FAIL(server_map < 0)) {
285+
perror("Unable to open " SERVER_MAP_PATH);
286+
goto cleanup;
287+
}
288+
281289
for (int i = 0; i < ARRAY_SIZE(tests) && !READ_ONCE(stop); i++) {
282290
struct test_sk_cfg *test = &tests[i];
283291
const struct sockaddr *addr;
292+
const int zero = 0;
293+
int err;
284294

285295
if (!test__start_subtest(test->name))
286296
continue;
287297
prepare_addr(test->addr, test->family, BIND_PORT, false);
288298
addr = (const struct sockaddr *)test->addr;
289299
server = start_server(addr, test->len, test->type);
290300
if (server == -1)
291-
goto cleanup;
301+
goto close;
302+
303+
err = bpf_map_update_elem(server_map, &zero, &server, BPF_ANY);
304+
if (CHECK_FAIL(err)) {
305+
perror("Unable to update server_map");
306+
goto close;
307+
}
292308

293309
/* connect to unbound ports */
294310
prepare_addr(test->addr, test->family, CONNECT_PORT,
@@ -302,7 +318,10 @@ void test_sk_assign(void)
302318

303319
close:
304320
close(server);
321+
close(server_map);
305322
cleanup:
323+
if (CHECK_FAIL(unlink(SERVER_MAP_PATH)))
324+
perror("Unable to unlink " SERVER_MAP_PATH);
306325
if (CHECK_FAIL(setns(self_net, CLONE_NEWNET)))
307326
perror("Failed to setns("NS_SELF")");
308327
close(self_net);

tools/testing/selftests/bpf/progs/test_sk_assign.c

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,26 @@
1616
#include <bpf/bpf_helpers.h>
1717
#include <bpf/bpf_endian.h>
1818

19+
/* Pin map under /sys/fs/bpf/tc/globals/<map name> */
20+
#define PIN_GLOBAL_NS 2
21+
22+
/* Must match struct bpf_elf_map layout from iproute2 */
23+
struct {
24+
__u32 type;
25+
__u32 size_key;
26+
__u32 size_value;
27+
__u32 max_elem;
28+
__u32 flags;
29+
__u32 id;
30+
__u32 pinning;
31+
} server_map SEC("maps") = {
32+
.type = BPF_MAP_TYPE_SOCKMAP,
33+
.size_key = sizeof(int),
34+
.size_value = sizeof(__u64),
35+
.max_elem = 1,
36+
.pinning = PIN_GLOBAL_NS,
37+
};
38+
1939
int _version SEC("version") = 1;
2040
char _license[] SEC("license") = "GPL";
2141

@@ -72,7 +92,9 @@ handle_udp(struct __sk_buff *skb, struct bpf_sock_tuple *tuple, bool ipv4)
7292
{
7393
struct bpf_sock_tuple ln = {0};
7494
struct bpf_sock *sk;
95+
const int zero = 0;
7596
size_t tuple_len;
97+
__be16 dport;
7698
int ret;
7799

78100
tuple_len = ipv4 ? sizeof(tuple->ipv4) : sizeof(tuple->ipv6);
@@ -83,32 +105,11 @@ handle_udp(struct __sk_buff *skb, struct bpf_sock_tuple *tuple, bool ipv4)
83105
if (sk)
84106
goto assign;
85107

86-
if (ipv4) {
87-
if (tuple->ipv4.dport != bpf_htons(4321))
88-
return TC_ACT_OK;
89-
90-
ln.ipv4.daddr = bpf_htonl(0x7f000001);
91-
ln.ipv4.dport = bpf_htons(1234);
92-
93-
sk = bpf_sk_lookup_udp(skb, &ln, sizeof(ln.ipv4),
94-
BPF_F_CURRENT_NETNS, 0);
95-
} else {
96-
if (tuple->ipv6.dport != bpf_htons(4321))
97-
return TC_ACT_OK;
98-
99-
/* Upper parts of daddr are already zero. */
100-
ln.ipv6.daddr[3] = bpf_htonl(0x1);
101-
ln.ipv6.dport = bpf_htons(1234);
102-
103-
sk = bpf_sk_lookup_udp(skb, &ln, sizeof(ln.ipv6),
104-
BPF_F_CURRENT_NETNS, 0);
105-
}
108+
dport = ipv4 ? tuple->ipv4.dport : tuple->ipv6.dport;
109+
if (dport != bpf_htons(4321))
110+
return TC_ACT_OK;
106111

107-
/* workaround: We can't do a single socket lookup here, because then
108-
* the compiler will likely spill tuple_len to the stack. This makes it
109-
* lose all bounds information in the verifier, which then rejects the
110-
* call as unsafe.
111-
*/
112+
sk = bpf_map_lookup_elem(&server_map, &zero);
112113
if (!sk)
113114
return TC_ACT_SHOT;
114115

@@ -123,7 +124,9 @@ handle_tcp(struct __sk_buff *skb, struct bpf_sock_tuple *tuple, bool ipv4)
123124
{
124125
struct bpf_sock_tuple ln = {0};
125126
struct bpf_sock *sk;
127+
const int zero = 0;
126128
size_t tuple_len;
129+
__be16 dport;
127130
int ret;
128131

129132
tuple_len = ipv4 ? sizeof(tuple->ipv4) : sizeof(tuple->ipv6);
@@ -137,32 +140,11 @@ handle_tcp(struct __sk_buff *skb, struct bpf_sock_tuple *tuple, bool ipv4)
137140
bpf_sk_release(sk);
138141
}
139142

140-
if (ipv4) {
141-
if (tuple->ipv4.dport != bpf_htons(4321))
142-
return TC_ACT_OK;
143+
dport = ipv4 ? tuple->ipv4.dport : tuple->ipv6.dport;
144+
if (dport != bpf_htons(4321))
145+
return TC_ACT_OK;
143146

144-
ln.ipv4.daddr = bpf_htonl(0x7f000001);
145-
ln.ipv4.dport = bpf_htons(1234);
146-
147-
sk = bpf_skc_lookup_tcp(skb, &ln, sizeof(ln.ipv4),
148-
BPF_F_CURRENT_NETNS, 0);
149-
} else {
150-
if (tuple->ipv6.dport != bpf_htons(4321))
151-
return TC_ACT_OK;
152-
153-
/* Upper parts of daddr are already zero. */
154-
ln.ipv6.daddr[3] = bpf_htonl(0x1);
155-
ln.ipv6.dport = bpf_htons(1234);
156-
157-
sk = bpf_skc_lookup_tcp(skb, &ln, sizeof(ln.ipv6),
158-
BPF_F_CURRENT_NETNS, 0);
159-
}
160-
161-
/* workaround: We can't do a single socket lookup here, because then
162-
* the compiler will likely spill tuple_len to the stack. This makes it
163-
* lose all bounds information in the verifier, which then rejects the
164-
* call as unsafe.
165-
*/
147+
sk = bpf_map_lookup_elem(&server_map, &zero);
166148
if (!sk)
167149
return TC_ACT_SHOT;
168150

0 commit comments

Comments
 (0)