Extend the tunnel drop reason test with the reasons added to the GRE receive path:
- two endpoints configured with different keys make the tunnel lookup on the receiver fail, which is reported as GRE_TUNNEL_NOT_FOUND, - setting the routing bit of the GRE header is reported as GRE_INVALID_HDR, and announcing GRE version 1, which has no handler unless PPTP is built in, is reported as UNHANDLED_PROTO. The last two corrupt the header of the received packets with tc pedit and are skipped when the ingress qdisc or the pedit action are not available. SKB_DROP_REASON_GRE_CSUM is not covered: veth hands the packets over with CHECKSUM_UNNECESSARY, so the GRE checksum is never validated and the reason cannot be reached without crafting the packets. Assisted-by: Claude-Code:claude-opus-5 Signed-off-by: Anton Danilov <[email protected]> --- .../selftests/net/tunnel_drop_reasons.sh | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tools/testing/selftests/net/tunnel_drop_reasons.sh b/tools/testing/selftests/net/tunnel_drop_reasons.sh index eb19967ae7dd..aad003f0efe5 100755 --- a/tools/testing/selftests/net/tunnel_drop_reasons.sh +++ b/tools/testing/selftests/net/tunnel_drop_reasons.sh @@ -20,6 +20,17 @@ # A control case, where both endpoints agree on the options, makes sure # that no tunnel drop reason is reported when packets are accepted. # +# The GRE specific reasons are checked as well: +# +# - a packet that matches no tunnel is reported as +# GRE_TUNNEL_NOT_FOUND. It is triggered here by giving the two +# endpoints different keys. +# +# - a header with the routing bit set is reported as GRE_INVALID_HDR, +# and a header announcing a GRE version nobody handles is reported as +# UNHANDLED_PROTO. Both are triggered by corrupting the GRE header +# on ingress with tc pedit, and are skipped if that is not available. +# # Drop reasons are read from the skb:kfree_skb tracepoint. A dedicated # trace instance is used so that the test does not disturb, and is not # disturbed by, anything else using the tracing facility. @@ -202,6 +213,47 @@ test_control() check_reason "gre: matching configuration (control)" "" } +# Corrupt one field of the GRE header of every IPv4 packet received by +# the receiver. $1 is a tc pedit munge expression, with offsets counted +# from the start of the IPv4 header. +corrupt_gre_header() +{ + ip netns exec "$NS_RCV" tc qdisc add dev veth_r ingress || return 1 + ip netns exec "$NS_RCV" tc filter add dev veth_r ingress \ + protocol ip matchall action pedit ex munge "$@" || return 1 +} + +test_tunnel_not_found() +{ + setup_ns_pair + # The two endpoints use different keys, so the lookup on the + # receiver finds no tunnel for the incoming packets. + add_gre "$NS_SND" "$SND_V4" "$RCV_V4" okey 1 ikey 1 + add_gre "$NS_RCV" "$RCV_V4" "$SND_V4" okey 2 ikey 2 + addr_tunnels + + check_reason "gre: tunnel not found" GRE_TUNNEL_NOT_FOUND +} + +# $1: test name, $2: expected reason, $3...: tc pedit munge expression +test_corrupted_header() +{ + local name=$1 want=$2 + + shift 2 + setup_ns_pair + add_gre "$NS_SND" "$SND_V4" "$RCV_V4" + add_gre "$NS_RCV" "$RCV_V4" "$SND_V4" + addr_tunnels + + if ! corrupt_gre_header "$@" 2>/dev/null; then + log_test_skip "$name" + return + fi + + check_reason "$name" "$want" +} + if [ "$(id -u)" -ne 0 ]; then echo "SKIP: need root" exit "$ksft_skip" @@ -217,6 +269,16 @@ test_opts_mismatch gre icsum test_control test_old_seq gre +test_tunnel_not_found +# The routing bit is the second most significant bit of the first byte +# of the GRE header, which follows the 20 byte IPv4 header. +test_corrupted_header "gre: routing bit set" GRE_INVALID_HDR \ + offset 20 u8 set 0x40 +# The GRE version sits in the low bits of the next byte. Version 1 is +# PPTP, which has no handler here. +test_corrupted_header "gre: unhandled GRE version" UNHANDLED_PROTO \ + offset 21 u8 set 0x01 + if [ -e /proc/sys/net/ipv6 ]; then test_opts_mismatch ip6gre iseq test_old_seq ip6gre -- 2.47.3

