-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: add tests for bpf_tcp_check_syncookie and bpf_skc_look…
…up_tcp Add tests which verify that the new helpers work for both IPv4 and IPv6, by forcing SYN cookies to always on. Use a new network namespace to avoid clobbering the global SYN cookie settings. Signed-off-by: Lorenz Bauer <lmb@cloudflare.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Lorenz Bauer
authored and
Alexei Starovoitov
committed
Mar 22, 2019
1 parent
5792d52
commit bafc0ba
Showing
6 changed files
with
434 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,4 +30,5 @@ test_netcnt | |
test_section_names | ||
test_tcpnotify_user | ||
test_libbpf | ||
test_tcp_check_syncookie_user | ||
alu32 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
// Copyright (c) 2018 Facebook | ||
// Copyright (c) 2019 Cloudflare | ||
|
||
#include <string.h> | ||
|
||
#include <linux/bpf.h> | ||
#include <linux/pkt_cls.h> | ||
#include <linux/if_ether.h> | ||
#include <linux/in.h> | ||
#include <linux/ip.h> | ||
#include <linux/ipv6.h> | ||
#include <sys/socket.h> | ||
#include <linux/tcp.h> | ||
|
||
#include "bpf_helpers.h" | ||
#include "bpf_endian.h" | ||
|
||
struct bpf_map_def SEC("maps") results = { | ||
.type = BPF_MAP_TYPE_ARRAY, | ||
.key_size = sizeof(__u32), | ||
.value_size = sizeof(__u64), | ||
.max_entries = 1, | ||
}; | ||
|
||
static __always_inline void check_syncookie(void *ctx, void *data, | ||
void *data_end) | ||
{ | ||
struct bpf_sock_tuple tup; | ||
struct bpf_sock *sk; | ||
struct ethhdr *ethh; | ||
struct iphdr *ipv4h; | ||
struct ipv6hdr *ipv6h; | ||
struct tcphdr *tcph; | ||
int ret; | ||
__u32 key = 0; | ||
__u64 value = 1; | ||
|
||
ethh = data; | ||
if (ethh + 1 > data_end) | ||
return; | ||
|
||
switch (bpf_ntohs(ethh->h_proto)) { | ||
case ETH_P_IP: | ||
ipv4h = data + sizeof(struct ethhdr); | ||
if (ipv4h + 1 > data_end) | ||
return; | ||
|
||
if (ipv4h->ihl != 5) | ||
return; | ||
|
||
tcph = data + sizeof(struct ethhdr) + sizeof(struct iphdr); | ||
if (tcph + 1 > data_end) | ||
return; | ||
|
||
tup.ipv4.saddr = ipv4h->saddr; | ||
tup.ipv4.daddr = ipv4h->daddr; | ||
tup.ipv4.sport = tcph->source; | ||
tup.ipv4.dport = tcph->dest; | ||
|
||
sk = bpf_skc_lookup_tcp(ctx, &tup, sizeof(tup.ipv4), | ||
BPF_F_CURRENT_NETNS, 0); | ||
if (!sk) | ||
return; | ||
|
||
if (sk->state != BPF_TCP_LISTEN) | ||
goto release; | ||
|
||
ret = bpf_tcp_check_syncookie(sk, ipv4h, sizeof(*ipv4h), | ||
tcph, sizeof(*tcph)); | ||
break; | ||
|
||
case ETH_P_IPV6: | ||
ipv6h = data + sizeof(struct ethhdr); | ||
if (ipv6h + 1 > data_end) | ||
return; | ||
|
||
if (ipv6h->nexthdr != IPPROTO_TCP) | ||
return; | ||
|
||
tcph = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); | ||
if (tcph + 1 > data_end) | ||
return; | ||
|
||
memcpy(tup.ipv6.saddr, &ipv6h->saddr, sizeof(tup.ipv6.saddr)); | ||
memcpy(tup.ipv6.daddr, &ipv6h->daddr, sizeof(tup.ipv6.daddr)); | ||
tup.ipv6.sport = tcph->source; | ||
tup.ipv6.dport = tcph->dest; | ||
|
||
sk = bpf_skc_lookup_tcp(ctx, &tup, sizeof(tup.ipv6), | ||
BPF_F_CURRENT_NETNS, 0); | ||
if (!sk) | ||
return; | ||
|
||
if (sk->state != BPF_TCP_LISTEN) | ||
goto release; | ||
|
||
ret = bpf_tcp_check_syncookie(sk, ipv6h, sizeof(*ipv6h), | ||
tcph, sizeof(*tcph)); | ||
break; | ||
|
||
default: | ||
return; | ||
} | ||
|
||
if (ret == 0) | ||
bpf_map_update_elem(&results, &key, &value, 0); | ||
|
||
release: | ||
bpf_sk_release(sk); | ||
} | ||
|
||
SEC("clsact/check_syncookie") | ||
int check_syncookie_clsact(struct __sk_buff *skb) | ||
{ | ||
check_syncookie(skb, (void *)(long)skb->data, | ||
(void *)(long)skb->data_end); | ||
return TC_ACT_OK; | ||
} | ||
|
||
SEC("xdp/check_syncookie") | ||
int check_syncookie_xdp(struct xdp_md *ctx) | ||
{ | ||
check_syncookie(ctx, (void *)(long)ctx->data, | ||
(void *)(long)ctx->data_end); | ||
return XDP_PASS; | ||
} | ||
|
||
char _license[] SEC("license") = "GPL"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#!/bin/sh | ||
# SPDX-License-Identifier: GPL-2.0 | ||
# Copyright (c) 2018 Facebook | ||
# Copyright (c) 2019 Cloudflare | ||
|
||
set -eu | ||
|
||
wait_for_ip() | ||
{ | ||
local _i | ||
printf "Wait for IP %s to become available " "$1" | ||
for _i in $(seq ${MAX_PING_TRIES}); do | ||
printf "." | ||
if ns1_exec ping -c 1 -W 1 "$1" >/dev/null 2>&1; then | ||
echo " OK" | ||
return | ||
fi | ||
sleep 1 | ||
done | ||
echo 1>&2 "ERROR: Timeout waiting for test IP to become available." | ||
exit 1 | ||
} | ||
|
||
get_prog_id() | ||
{ | ||
awk '/ id / {sub(/.* id /, "", $0); print($1)}' | ||
} | ||
|
||
ns1_exec() | ||
{ | ||
ip netns exec ns1 "$@" | ||
} | ||
|
||
setup() | ||
{ | ||
ip netns add ns1 | ||
ns1_exec ip link set lo up | ||
|
||
ns1_exec sysctl -w net.ipv4.tcp_syncookies=2 | ||
|
||
wait_for_ip 127.0.0.1 | ||
wait_for_ip ::1 | ||
} | ||
|
||
cleanup() | ||
{ | ||
ip netns del ns1 2>/dev/null || : | ||
} | ||
|
||
main() | ||
{ | ||
trap cleanup EXIT 2 3 6 15 | ||
setup | ||
|
||
printf "Testing clsact..." | ||
ns1_exec tc qdisc add dev "${TEST_IF}" clsact | ||
ns1_exec tc filter add dev "${TEST_IF}" ingress \ | ||
bpf obj "${BPF_PROG_OBJ}" sec "${CLSACT_SECTION}" da | ||
|
||
BPF_PROG_ID=$(ns1_exec tc filter show dev "${TEST_IF}" ingress | \ | ||
get_prog_id) | ||
ns1_exec "${PROG}" "${BPF_PROG_ID}" | ||
ns1_exec tc qdisc del dev "${TEST_IF}" clsact | ||
|
||
printf "Testing XDP..." | ||
ns1_exec ip link set "${TEST_IF}" xdp \ | ||
object "${BPF_PROG_OBJ}" section "${XDP_SECTION}" | ||
BPF_PROG_ID=$(ns1_exec ip link show "${TEST_IF}" | get_prog_id) | ||
ns1_exec "${PROG}" "${BPF_PROG_ID}" | ||
} | ||
|
||
DIR=$(dirname $0) | ||
TEST_IF=lo | ||
MAX_PING_TRIES=5 | ||
BPF_PROG_OBJ="${DIR}/test_tcp_check_syncookie_kern.o" | ||
CLSACT_SECTION="clsact/check_syncookie" | ||
XDP_SECTION="xdp/check_syncookie" | ||
BPF_PROG_ID=0 | ||
PROG="${DIR}/test_tcp_check_syncookie_user" | ||
|
||
main |
Oops, something went wrong.