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


Reply via email to