AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/09/13 04:15 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch series purely annotates existing packet drop points in IPv4/IPv6 GRE and IP tunneling code with specific enum skb_drop_reason values passed to kfree_skb_reason(). This enriches the kfree_skb tracepoint without altering control flow, packet acceptance/rejection decisions, or kernel data structures. As purely tracepoint-related annotation changes that do not modify executable logic or invariants, fuzzing is not warranted.",
  "WorthFuzzing": false
}

1/1 2026/09/13 04:15 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 40bd7d2fc591a6070762fa2effffbe26cab83dd8\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sun Sep 13 04:15:35 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h\nindex 12f9096515912..30378a0d22726 100644\n--- a/include/net/dropreason-core.h\n+++ b/include/net/dropreason-core.h\n@@ -129,6 +129,12 @@\n \tFN(PSP_INPUT)\t\t\t\\\n \tFN(PSP_OUTPUT)\t\t\t\\\n \tFN(RECURSION_LIMIT)\t\t\\\n+\tFN(TNL_OPT_MISMATCH)\t\t\\\n+\tFN(TNL_OLD_SEQ)\t\t\t\\\n+\tFN(GRE_INVALID_HDR)\t\t\\\n+\tFN(GRE_CSUM)\t\t\t\\\n+\tFN(GRE_TUNNEL_NOT_FOUND)\t\\\n+\tFN(TNL_ENCAP)\t\t\t\\\n \tFNe(MAX)\n \n /**\n@@ -612,6 +618,38 @@ enum skb_drop_reason {\n \tSKB_DROP_REASON_PSP_OUTPUT,\n \t/** @SKB_DROP_REASON_RECURSION_LIMIT: Dead loop on virtual device. */\n \tSKB_DROP_REASON_RECURSION_LIMIT,\n+\t/**\n+\t * @SKB_DROP_REASON_TNL_OPT_MISMATCH: the tunnel options\n+\t * carried by the packet do not match the tunnel configuration, e.g.\n+\t * a GRE tunnel configured with 'icsum' or 'iseq' received a packet\n+\t * with no checksum or no sequence number.\n+\t */\n+\tSKB_DROP_REASON_TNL_OPT_MISMATCH,\n+\t/**\n+\t * @SKB_DROP_REASON_TNL_OLD_SEQ: the sequence number carried\n+\t * by the packet is older than the one expected by the tunnel, e.g.\n+\t * after the remote endpoint restarted and reset its sequence\n+\t * numbering.\n+\t */\n+\tSKB_DROP_REASON_TNL_OLD_SEQ,\n+\t/**\n+\t * @SKB_DROP_REASON_GRE_INVALID_HDR: the GRE header is invalid, e.g.\n+\t * an unsupported version or the routing bit is set.\n+\t */\n+\tSKB_DROP_REASON_GRE_INVALID_HDR,\n+\t/** @SKB_DROP_REASON_GRE_CSUM: GRE checksum error */\n+\tSKB_DROP_REASON_GRE_CSUM,\n+\t/**\n+\t * @SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND: no GRE tunnel found for the\n+\t * endpoints and the key the packet carries.\n+\t */\n+\tSKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND,\n+\t/**\n+\t * @SKB_DROP_REASON_TNL_ENCAP: failed to build the\n+\t * encapsulation header of a tunnel, e.g. an unknown or\n+\t * unregistered encapsulation type.\n+\t */\n+\tSKB_DROP_REASON_TNL_ENCAP,\n \t/**\n \t * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which\n \t * shouldn't be used as a real 'reason' - only for tracing code gen\ndiff --git a/include/net/gre.h b/include/net/gre.h\nindex b55f67ecd2fc4..a63f26c3f78ed 100644\n--- a/include/net/gre.h\n+++ b/include/net/gre.h\n@@ -33,7 +33,7 @@ int gre_add_protocol(const struct gre_protocol *proto, u8 version);\n int gre_del_protocol(const struct gre_protocol *proto, u8 version);\n \n int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n-\t\t     bool *csum_err, __be16 proto, int nhs);\n+\t\t     enum skb_drop_reason *reason, __be16 proto, int nhs);\n \n static inline bool netif_is_gretap(const struct net_device *dev)\n {\ndiff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h\nindex b99805ee2fd14..95f6d12254df6 100644\n--- a/include/net/ip6_tunnel.h\n+++ b/include/net/ip6_tunnel.h\n@@ -143,7 +143,8 @@ int ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,\n \t\t     const struct in6_addr *raddr);\n int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n-\t\t struct flowi6 *fl6, int encap_limit, __u32 *pmtu, __u8 proto);\n+\t\t struct flowi6 *fl6, int encap_limit, __u32 *pmtu, __u8 proto,\n+\t\t enum skb_drop_reason *reason);\n __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);\n __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,\n \t\t\t     const struct in6_addr *raddr);\ndiff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c\nindex 96fd7dc6d82dd..efd5f60a9c591 100644\n--- a/net/ipv4/gre_demux.c\n+++ b/net/ipv4/gre_demux.c\n@@ -58,26 +58,43 @@ EXPORT_SYMBOL_GPL(gre_del_protocol);\n \n /* Fills in tpi and returns header length to be pulled.\n  * Note that caller must use pskb_may_pull() before pulling GRE header.\n+ *\n+ * @reason is only written when the header is rejected, so the caller has\n+ * to initialise it before the call.\n+ *\n+ * A NULL @reason means that the caller is not interested in the drop\n+ * reason, and also that the checksum must not be verified.  This is what\n+ * the ICMP error handlers need, as they only get a part of the original\n+ * packet.\n  */\n int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n-\t\t     bool *csum_err, __be16 proto, int nhs)\n+\t\t     enum skb_drop_reason *reason, __be16 proto, int nhs)\n {\n \tconst struct gre_base_hdr *greh;\n \t__be32 *options;\n \tint hdr_len;\n \n-\tif (unlikely(!pskb_may_pull(skb, nhs + sizeof(struct gre_base_hdr))))\n+\tif (unlikely(!pskb_may_pull(skb, nhs + sizeof(struct gre_base_hdr)))) {\n+\t\tif (reason)\n+\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\treturn -EINVAL;\n+\t}\n \n \tgreh = (struct gre_base_hdr *)(skb-\u003edata + nhs);\n-\tif (unlikely(greh-\u003eflags \u0026 (GRE_VERSION | GRE_ROUTING)))\n+\tif (unlikely(greh-\u003eflags \u0026 (GRE_VERSION | GRE_ROUTING))) {\n+\t\tif (reason)\n+\t\t\t*reason = SKB_DROP_REASON_GRE_INVALID_HDR;\n \t\treturn -EINVAL;\n+\t}\n \n \tgre_flags_to_tnl_flags(tpi-\u003eflags, greh-\u003eflags);\n \thdr_len = gre_calc_hlen(tpi-\u003eflags);\n \n-\tif (!pskb_may_pull(skb, nhs + hdr_len))\n+\tif (!pskb_may_pull(skb, nhs + hdr_len)) {\n+\t\tif (reason)\n+\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\treturn -EINVAL;\n+\t}\n \n \tgreh = (struct gre_base_hdr *)(skb-\u003edata + nhs);\n \ttpi-\u003eproto = greh-\u003eprotocol;\n@@ -87,8 +104,8 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n \t\tif (!skb_checksum_simple_validate(skb)) {\n \t\t\tskb_checksum_try_convert(skb, IPPROTO_GRE,\n \t\t\t\t\t\t null_compute_pseudo);\n-\t\t} else if (csum_err) {\n-\t\t\t*csum_err = true;\n+\t\t} else if (reason) {\n+\t\t\t*reason = SKB_DROP_REASON_GRE_CSUM;\n \t\t\treturn -EINVAL;\n \t\t}\n \n@@ -116,8 +133,11 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n \n \t\tval = skb_header_pointer(skb, nhs + hdr_len,\n \t\t\t\t\t sizeof(_val), \u0026_val);\n-\t\tif (!val)\n+\t\tif (!val) {\n+\t\t\tif (reason)\n+\t\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\t\treturn -EINVAL;\n+\t\t}\n \t\ttpi-\u003eproto = proto;\n \t\tif ((*val \u0026 0xF0) != 0x40)\n \t\t\thdr_len += 4;\n@@ -132,8 +152,11 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n \t    greh-\u003eprotocol == htons(ETH_P_ERSPAN2)) {\n \t\tstruct erspan_base_hdr *ershdr;\n \n-\t\tif (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr)))\n+\t\tif (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr))) {\n+\t\t\tif (reason)\n+\t\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\t\treturn -EINVAL;\n+\t\t}\n \n \t\tershdr = (struct erspan_base_hdr *)(skb-\u003edata + nhs + hdr_len);\n \t\ttpi-\u003ekey = cpu_to_be32(get_session_id(ershdr));\n@@ -145,16 +168,20 @@ EXPORT_SYMBOL(gre_parse_header);\n \n static int gre_rcv(struct sk_buff *skb)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tconst struct gre_protocol *proto;\n \tu8 ver;\n \tint ret;\n \n-\tif (!pskb_may_pull(skb, 12))\n+\treason = pskb_may_pull_reason(skb, 12);\n+\tif (reason)\n \t\tgoto drop;\n \n \tver = skb-\u003edata[1]\u00260x7f;\n-\tif (ver \u003e= GREPROTO_MAX)\n+\tif (ver \u003e= GREPROTO_MAX) {\n+\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\tgoto drop;\n+\t}\n \n \trcu_read_lock();\n \tproto = rcu_dereference(gre_proto[ver]);\n@@ -167,11 +194,11 @@ static int gre_rcv(struct sk_buff *skb)\n drop_nohandler:\n \trcu_read_unlock();\n \tdev_core_stats_rx_nohandler_inc(skb-\u003edev);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, SKB_DROP_REASON_UNHANDLED_PROTO);\n \treturn NET_RX_DROP;\n drop:\n \tdev_core_stats_rx_dropped_inc(skb-\u003edev);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn NET_RX_DROP;\n }\n \ndiff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c\nindex 82309efd417e0..7b9687f1de0c4 100644\n--- a/net/ipv4/ip_gre.c\n+++ b/net/ipv4/ip_gre.c\n@@ -265,7 +265,7 @@ static bool is_erspan_type1(int gre_hdr_len)\n }\n \n static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n-\t\t      int gre_hdr_len)\n+\t\t      int gre_hdr_len, enum skb_drop_reason *reason)\n {\n \tstruct net *net = dev_net(skb-\u003edev);\n \tstruct metadata_dst *tun_dst = NULL;\n@@ -289,8 +289,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n \t\t\t\t\t  iph-\u003esaddr, iph-\u003edaddr, 0);\n \t} else {\n \t\tif (unlikely(!pskb_may_pull(skb,\n-\t\t\t\t\t    gre_hdr_len + sizeof(*ershdr))))\n+\t\t\t\t\t    gre_hdr_len + sizeof(*ershdr)))) {\n+\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\t\treturn PACKET_REJECT;\n+\t\t}\n \n \t\tershdr = (struct erspan_base_hdr *)(skb-\u003edata + gre_hdr_len);\n \t\tver = ershdr-\u003ever;\n@@ -306,8 +308,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n \t\telse\n \t\t\tlen = gre_hdr_len + erspan_hdr_len(ver);\n \n-\t\tif (unlikely(!pskb_may_pull(skb, len)))\n+\t\tif (unlikely(!pskb_may_pull(skb, len))) {\n+\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\t\treturn PACKET_REJECT;\n+\t\t}\n \n \t\tif (__iptunnel_pull_header(skb,\n \t\t\t\t\t   len,\n@@ -327,8 +331,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n \n \t\t\ttun_dst = ip_tun_rx_dst(skb, flags,\n \t\t\t\t\t\ttun_id, sizeof(*md));\n-\t\t\tif (!tun_dst)\n+\t\t\tif (!tun_dst) {\n+\t\t\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\t\t\treturn PACKET_REJECT;\n+\t\t\t}\n \n \t\t\t/* MUST set options_len before referencing options */\n \t\t\tinfo = \u0026tun_dst-\u003eu.tun_info;\n@@ -356,15 +362,17 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n \t\tip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);\n \t\treturn PACKET_RCVD;\n \t}\n+\t*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;\n \treturn PACKET_REJECT;\n \n drop:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, SKB_DROP_REASON_HDR_TRUNC);\n \treturn PACKET_RCVD;\n }\n \n static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,\n-\t\t       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)\n+\t\t       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto,\n+\t\t       enum skb_drop_reason *reason)\n {\n \tstruct metadata_dst *tun_dst = NULL;\n \tconst struct iphdr *iph;\n@@ -400,22 +408,25 @@ static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,\n \n \t\t\ttun_id = key32_to_tunnel_id(tpi-\u003ekey);\n \t\t\ttun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);\n-\t\t\tif (!tun_dst)\n+\t\t\tif (!tun_dst) {\n+\t\t\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\t\t\treturn PACKET_REJECT;\n+\t\t\t}\n \t\t}\n \n \t\tip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);\n \t\treturn PACKET_RCVD;\n \t}\n+\t*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;\n \treturn PACKET_NEXT;\n \n drop:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, SKB_DROP_REASON_HDR_TRUNC);\n \treturn PACKET_RCVD;\n }\n \n static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,\n-\t\t     int hdr_len)\n+\t\t     int hdr_len, enum skb_drop_reason *reason)\n {\n \tstruct net *net = dev_net(skb-\u003edev);\n \tstruct ip_tunnel_net *itn;\n@@ -426,21 +437,21 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,\n \telse\n \t\titn = net_generic(net, ipgre_net_id);\n \n-\tres = __ipgre_rcv(skb, tpi, itn, hdr_len, false);\n+\tres = __ipgre_rcv(skb, tpi, itn, hdr_len, false, reason);\n \tif (res == PACKET_NEXT \u0026\u0026 tpi-\u003eproto == htons(ETH_P_TEB)) {\n \t\t/* ipgre tunnels in collect metadata mode should receive\n \t\t * also ETH_P_TEB traffic.\n \t\t */\n \t\titn = net_generic(net, ipgre_net_id);\n-\t\tres = __ipgre_rcv(skb, tpi, itn, hdr_len, true);\n+\t\tres = __ipgre_rcv(skb, tpi, itn, hdr_len, true, reason);\n \t}\n \treturn res;\n }\n \n static int gre_rcv(struct sk_buff *skb)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct tnl_ptk_info tpi;\n-\tbool csum_err = false;\n \tint hdr_len;\n \n #ifdef CONFIG_NET_IPGRE_BROADCAST\n@@ -451,25 +462,25 @@ static int gre_rcv(struct sk_buff *skb)\n \t}\n #endif\n \n-\thdr_len = gre_parse_header(skb, \u0026tpi, \u0026csum_err, htons(ETH_P_IP), 0);\n+\thdr_len = gre_parse_header(skb, \u0026tpi, \u0026reason, htons(ETH_P_IP), 0);\n \tif (hdr_len \u003c 0)\n \t\tgoto drop;\n \n \tif (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||\n \t\t     tpi.proto == htons(ETH_P_ERSPAN2))) {\n-\t\tif (erspan_rcv(skb, \u0026tpi, hdr_len) == PACKET_RCVD)\n+\t\tif (erspan_rcv(skb, \u0026tpi, hdr_len, \u0026reason) == PACKET_RCVD)\n \t\t\treturn 0;\n \t\tgoto out;\n \t}\n \n-\tif (ipgre_rcv(skb, \u0026tpi, hdr_len) == PACKET_RCVD)\n+\tif (ipgre_rcv(skb, \u0026tpi, hdr_len, \u0026reason) == PACKET_RCVD)\n \t\treturn 0;\n \n out:\n \ticmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);\n drop:\n \tdev_core_stats_rx_dropped_inc(skb-\u003edev);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn 0;\n }\n \n@@ -496,6 +507,7 @@ static int gre_handle_offloads(struct sk_buff *skb, bool csum)\n static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\t\t__be16 proto)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel *tunnel = netdev_priv(dev);\n \tIP_TUNNEL_DECLARE_FLAGS(flags) = { };\n \tstruct ip_tunnel_info *tun_info;\n@@ -504,19 +516,25 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \ttun_info = skb_tunnel_info(skb);\n \tif (unlikely(!tun_info || !(tun_info-\u003emode \u0026 IP_TUNNEL_INFO_TX) ||\n-\t\t     ip_tunnel_info_af(tun_info) != AF_INET))\n+\t\t     ip_tunnel_info_af(tun_info) != AF_INET)) {\n+\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\tgoto err_free_skb;\n+\t}\n \n \tkey = \u0026tun_info-\u003ekey;\n \ttunnel_hlen = gre_calc_hlen(key-\u003etun_flags);\n \n-\tif (skb_cow_head(skb, dev-\u003eneeded_headroom))\n+\tif (skb_cow_head(skb, dev-\u003eneeded_headroom)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto err_free_skb;\n+\t}\n \n \t/* Push Tunnel header. */\n \tif (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,\n-\t\t\t\t\t      tunnel-\u003eparms.o_flags)))\n+\t\t\t\t\t      tunnel-\u003eparms.o_flags))) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto err_free_skb;\n+\t}\n \n \t__set_bit(IP_TUNNEL_CSUM_BIT, flags);\n \t__set_bit(IP_TUNNEL_KEY_BIT, flags);\n@@ -533,12 +551,13 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,\n \treturn;\n \n err_free_skb:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \tDEV_STATS_INC(dev, tx_dropped);\n }\n \n static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel *tunnel = netdev_priv(dev);\n \tIP_TUNNEL_DECLARE_FLAGS(flags) = { };\n \tstruct ip_tunnel_info *tun_info;\n@@ -552,29 +571,41 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)\n \n \ttun_info = skb_tunnel_info(skb);\n \tif (unlikely(!tun_info || !(tun_info-\u003emode \u0026 IP_TUNNEL_INFO_TX) ||\n-\t\t     ip_tunnel_info_af(tun_info) != AF_INET))\n+\t\t     ip_tunnel_info_af(tun_info) != AF_INET)) {\n+\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\tgoto err_free_skb;\n+\t}\n \n \tkey = \u0026tun_info-\u003ekey;\n-\tif (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT, tun_info-\u003ekey.tun_flags))\n+\tif (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT, tun_info-\u003ekey.tun_flags)) {\n+\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\tgoto err_free_skb;\n-\tif (tun_info-\u003eoptions_len \u003c sizeof(*md))\n+\t}\n+\tif (tun_info-\u003eoptions_len \u003c sizeof(*md)) {\n+\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\tgoto err_free_skb;\n+\t}\n \tmd = ip_tunnel_info_opts(tun_info);\n \n \t/* ERSPAN has fixed 8 byte GRE header */\n \tversion = md-\u003eversion;\n \ttunnel_hlen = 8 + erspan_hdr_len(version);\n \n-\tif (skb_cow_head(skb, dev-\u003eneeded_headroom))\n+\tif (skb_cow_head(skb, dev-\u003eneeded_headroom)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto err_free_skb;\n+\t}\n \n-\tif (gre_handle_offloads(skb, false))\n+\tif (gre_handle_offloads(skb, false)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto err_free_skb;\n+\t}\n \n \tif (skb-\u003elen \u003e dev-\u003emtu + dev-\u003ehard_header_len) {\n-\t\tif (pskb_trim(skb, dev-\u003emtu + dev-\u003ehard_header_len))\n+\t\tif (pskb_trim(skb, dev-\u003emtu + dev-\u003ehard_header_len)) {\n+\t\t\treason = SKB_DROP_REASON_NOMEM;\n \t\t\tgoto err_free_skb;\n+\t\t}\n \t\ttruncate = true;\n \t}\n \n@@ -606,6 +637,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\t\t\t       truncate, true);\n \t\tproto = htons(ETH_P_ERSPAN2);\n \t} else {\n+\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\tgoto err_free_skb;\n \t}\n \n@@ -618,7 +650,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)\n \treturn;\n \n err_free_skb:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \tDEV_STATS_INC(dev, tx_dropped);\n }\n \n@@ -649,11 +681,13 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)\n static netdev_tx_t ipgre_xmit(struct sk_buff *skb,\n \t\t\t      struct net_device *dev)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel *tunnel = netdev_priv(dev);\n \tIP_TUNNEL_DECLARE_FLAGS(flags);\n \tconst struct iphdr *tnl_params;\n \n-\tif (!pskb_inet_may_pull(skb))\n+\treason = pskb_inet_may_pull_reason(skb);\n+\tif (reason)\n \t\tgoto free_skb;\n \n \tif (tunnel-\u003ecollect_md) {\n@@ -664,10 +698,13 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,\n \tif (dev-\u003eheader_ops) {\n \t\tint pull_len = tunnel-\u003ehlen + sizeof(struct iphdr);\n \n-\t\tif (skb_cow_head(skb, 0))\n+\t\tif (skb_cow_head(skb, 0)) {\n+\t\t\treason = SKB_DROP_REASON_NOMEM;\n \t\t\tgoto free_skb;\n+\t\t}\n \n-\t\tif (!pskb_may_pull(skb, pull_len))\n+\t\treason = pskb_may_pull_reason(skb, pull_len);\n+\t\tif (reason)\n \t\t\tgoto free_skb;\n \n \t\ttnl_params = (const struct iphdr *)skb-\u003edata;\n@@ -677,25 +714,31 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,\n \t\tskb_reset_mac_header(skb);\n \n \t\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026\n-\t\t    skb_checksum_start(skb) \u003c skb-\u003edata)\n+\t\t    skb_checksum_start(skb) \u003c skb-\u003edata) {\n+\t\t\treason = SKB_DROP_REASON_SKB_CSUM;\n \t\t\tgoto free_skb;\n+\t\t}\n \t} else {\n-\t\tif (skb_cow_head(skb, dev-\u003eneeded_headroom))\n+\t\tif (skb_cow_head(skb, dev-\u003eneeded_headroom)) {\n+\t\t\treason = SKB_DROP_REASON_NOMEM;\n \t\t\tgoto free_skb;\n+\t\t}\n \n \t\ttnl_params = \u0026tunnel-\u003eparms.iph;\n \t}\n \n \tip_tunnel_flags_copy(flags, tunnel-\u003eparms.o_flags);\n \n-\tif (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags)))\n+\tif (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags))) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto free_skb;\n+\t}\n \n \t__gre_xmit(skb, dev, tnl_params, skb-\u003eprotocol, flags);\n \treturn NETDEV_TX_OK;\n \n free_skb:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \tDEV_STATS_INC(dev, tx_dropped);\n \treturn NETDEV_TX_OK;\n }\n@@ -703,12 +746,14 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,\n static netdev_tx_t erspan_xmit(struct sk_buff *skb,\n \t\t\t       struct net_device *dev)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel *tunnel = netdev_priv(dev);\n \tIP_TUNNEL_DECLARE_FLAGS(flags);\n \tbool truncate = false;\n \t__be16 proto;\n \n-\tif (!pskb_inet_may_pull(skb))\n+\treason = pskb_inet_may_pull_reason(skb);\n+\tif (reason)\n \t\tgoto free_skb;\n \n \tif (tunnel-\u003ecollect_md) {\n@@ -716,15 +761,21 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,\n \t\treturn NETDEV_TX_OK;\n \t}\n \n-\tif (gre_handle_offloads(skb, false))\n+\tif (gre_handle_offloads(skb, false)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto free_skb;\n+\t}\n \n-\tif (skb_cow_head(skb, dev-\u003eneeded_headroom))\n+\tif (skb_cow_head(skb, dev-\u003eneeded_headroom)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto free_skb;\n+\t}\n \n \tif (skb-\u003elen \u003e dev-\u003emtu + dev-\u003ehard_header_len) {\n-\t\tif (pskb_trim(skb, dev-\u003emtu + dev-\u003ehard_header_len))\n+\t\tif (pskb_trim(skb, dev-\u003emtu + dev-\u003ehard_header_len)) {\n+\t\t\treason = SKB_DROP_REASON_NOMEM;\n \t\t\tgoto free_skb;\n+\t\t}\n \t\ttruncate = true;\n \t}\n \n@@ -745,6 +796,7 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,\n \t\t\t\t       truncate, true);\n \t\tproto = htons(ETH_P_ERSPAN2);\n \t} else {\n+\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\tgoto free_skb;\n \t}\n \n@@ -753,7 +805,7 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,\n \treturn NETDEV_TX_OK;\n \n free_skb:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \tDEV_STATS_INC(dev, tx_dropped);\n \treturn NETDEV_TX_OK;\n }\n@@ -761,10 +813,12 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,\n static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,\n \t\t\t\tstruct net_device *dev)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel *tunnel = netdev_priv(dev);\n \tIP_TUNNEL_DECLARE_FLAGS(flags);\n \n-\tif (!pskb_inet_may_pull(skb))\n+\treason = pskb_inet_may_pull_reason(skb);\n+\tif (reason)\n \t\tgoto free_skb;\n \n \tif (tunnel-\u003ecollect_md) {\n@@ -774,17 +828,21 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,\n \n \tip_tunnel_flags_copy(flags, tunnel-\u003eparms.o_flags);\n \n-\tif (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags)))\n+\tif (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags))) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto free_skb;\n+\t}\n \n-\tif (skb_cow_head(skb, dev-\u003eneeded_headroom))\n+\tif (skb_cow_head(skb, dev-\u003eneeded_headroom)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto free_skb;\n+\t}\n \n \t__gre_xmit(skb, dev, \u0026tunnel-\u003eparms.iph, htons(ETH_P_TEB), flags);\n \treturn NETDEV_TX_OK;\n \n free_skb:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \tDEV_STATS_INC(dev, tx_dropped);\n \treturn NETDEV_TX_OK;\n }\ndiff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c\nindex 13b5e35e8790b..e7757c0a09be4 100644\n--- a/net/ipv4/ip_tunnel.c\n+++ b/net/ipv4/ip_tunnel.c\n@@ -378,6 +378,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,\n \t\t  const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,\n \t\t  bool log_ecn_error)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tconst struct iphdr *iph = ip_hdr(skb);\n \tint nh, err;\n \n@@ -392,14 +393,22 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,\n \t    test_bit(IP_TUNNEL_CSUM_BIT, tpi-\u003eflags)) {\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_crc_errors);\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\treason = SKB_DROP_REASON_TNL_OPT_MISMATCH;\n \t\tgoto drop;\n \t}\n \n \tif (test_bit(IP_TUNNEL_SEQ_BIT, tunnel-\u003eparms.i_flags)) {\n-\t\tif (!test_bit(IP_TUNNEL_SEQ_BIT, tpi-\u003eflags) ||\n-\t\t    (tunnel-\u003ei_seqno \u0026\u0026 (s32)(ntohl(tpi-\u003eseq) - tunnel-\u003ei_seqno) \u003c 0)) {\n+\t\tif (!test_bit(IP_TUNNEL_SEQ_BIT, tpi-\u003eflags)) {\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_fifo_errors);\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\t\treason = SKB_DROP_REASON_TNL_OPT_MISMATCH;\n+\t\t\tgoto drop;\n+\t\t}\n+\t\tif (tunnel-\u003ei_seqno \u0026\u0026\n+\t\t    (s32)(ntohl(tpi-\u003eseq) - tunnel-\u003ei_seqno) \u003c 0) {\n+\t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_fifo_errors);\n+\t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\t\treason = SKB_DROP_REASON_TNL_OLD_SEQ;\n \t\t\tgoto drop;\n \t\t}\n \t\ttunnel-\u003ei_seqno = ntohl(tpi-\u003eseq) + 1;\n@@ -413,7 +422,8 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,\n \n \tskb_set_network_header(skb, (tunnel-\u003edev-\u003etype == ARPHRD_ETHER) ? ETH_HLEN : 0);\n \n-\tif (!pskb_inet_may_pull(skb)) {\n+\treason = pskb_inet_may_pull_reason(skb);\n+\tif (reason) {\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_length_errors);\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n \t\tgoto drop;\n@@ -428,6 +438,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,\n \t\tif (err \u003e 1) {\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_frame_errors);\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\t\treason = SKB_DROP_REASON_IP_TUNNEL_ECN;\n \t\t\tgoto drop;\n \t\t}\n \t}\n@@ -451,7 +462,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,\n drop:\n \tif (tun_dst)\n \t\tdst_release((struct dst_entry *)tun_dst);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn 0;\n }\n EXPORT_SYMBOL_GPL(ip_tunnel_rcv);\n@@ -569,6 +580,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,\n void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\t       u8 proto, int tunnel_hlen)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel *tunnel = netdev_priv(dev);\n \tu32 headroom = sizeof(struct iphdr);\n \tstruct ip_tunnel_info *tun_info;\n@@ -582,8 +594,10 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \ttun_info = skb_tunnel_info(skb);\n \tif (unlikely(!tun_info || !(tun_info-\u003emode \u0026 IP_TUNNEL_INFO_TX) ||\n-\t\t     ip_tunnel_info_af(tun_info) != AF_INET))\n+\t\t     ip_tunnel_info_af(tun_info) != AF_INET)) {\n+\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\tgoto tx_error;\n+\t}\n \tkey = \u0026tun_info-\u003ekey;\n \tmemset(\u0026(IPCB(skb)-\u003eopt), 0, sizeof(IPCB(skb)-\u003eopt));\n \tinner_iph = (const struct iphdr *)skb_inner_network_header(skb);\n@@ -602,8 +616,10 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \tif (!tunnel_hlen)\n \t\ttunnel_hlen = ip_encap_hlen(\u0026tun_info-\u003eencap);\n \n-\tif (ip_tunnel_encap(skb, \u0026tun_info-\u003eencap, \u0026proto, \u0026fl4) \u003c 0)\n+\tif (ip_tunnel_encap(skb, \u0026tun_info-\u003eencap, \u0026proto, \u0026fl4) \u003c 0) {\n+\t\treason = SKB_DROP_REASON_TNL_ENCAP;\n \t\tgoto tx_error;\n+\t}\n \n \tuse_cache = ip_tunnel_dst_cache_usable(skb, tun_info);\n \tif (use_cache)\n@@ -612,6 +628,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\trt = ip_route_output_key(tunnel-\u003enet, \u0026fl4);\n \t\tif (IS_ERR(rt)) {\n \t\t\tDEV_STATS_INC(dev, tx_carrier_errors);\n+\t\t\treason = SKB_DROP_REASON_IP_OUTNOROUTES;\n \t\t\tgoto tx_error;\n \t\t}\n \t\tif (use_cache)\n@@ -621,6 +638,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \tif (rt-\u003edst.dev == dev) {\n \t\tip_rt_put(rt);\n \t\tDEV_STATS_INC(dev, collisions);\n+\t\treason = SKB_DROP_REASON_RECURSION_LIMIT;\n \t\tgoto tx_error;\n \t}\n \n@@ -629,6 +647,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \tif (tnl_update_pmtu(dev, skb, rt, df, inner_iph, tunnel_hlen,\n \t\t\t    key-\u003eu.ipv4.dst, true)) {\n \t\tip_rt_put(rt);\n+\t\treason = SKB_DROP_REASON_PKT_TOO_BIG;\n \t\tgoto tx_error;\n \t}\n \n@@ -646,6 +665,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \theadroom += LL_RESERVED_SPACE(rt-\u003edst.dev) + rt-\u003edst.header_len;\n \tif (skb_cow_head(skb, headroom)) {\n \t\tip_rt_put(rt);\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto tx_dropped;\n \t}\n \n@@ -660,13 +680,14 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n tx_dropped:\n \tDEV_STATS_INC(dev, tx_dropped);\n kfree:\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n }\n EXPORT_SYMBOL_GPL(ip_md_tunnel_xmit);\n \n void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\t    const struct iphdr *tnl_params, u8 protocol)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel *tunnel = netdev_priv(dev);\n \tstruct ip_tunnel_info *tun_info = NULL;\n \tconst struct iphdr *inner_iph;\n@@ -694,9 +715,15 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \t\tif (!skb_dst(skb)) {\n \t\t\tDEV_STATS_INC(dev, tx_fifo_errors);\n+\t\t\treason = SKB_DROP_REASON_NO_TX_TARGET;\n \t\t\tgoto tx_error;\n \t\t}\n \n+\t\t/* Only the branches below can derive a destination.  If\n+\t\t * none of them matches, the payload protocol is not one\n+\t\t * this tunnel can carry.\n+\t\t */\n+\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\ttun_info = skb_tunnel_info(skb);\n \t\tif (tun_info \u0026\u0026 (tun_info-\u003emode \u0026 IP_TUNNEL_INFO_TX) \u0026\u0026\n \t\t    ip_tunnel_info_af(tun_info) == AF_INET \u0026\u0026\n@@ -717,8 +744,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \t\t\tneigh = dst_neigh_lookup(skb_dst(skb),\n \t\t\t\t\t\t \u0026ipv6_hdr(skb)-\u003edaddr);\n-\t\t\tif (!neigh)\n+\t\t\tif (!neigh) {\n+\t\t\t\treason = SKB_DROP_REASON_NEIGH_CREATEFAIL;\n \t\t\t\tgoto tx_error;\n+\t\t\t}\n \n \t\t\taddr6 = (const struct in6_addr *)\u0026neigh-\u003eprimary_key;\n \t\t\taddr_type = ipv6_addr_type(addr6);\n@@ -735,8 +764,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\t\t\tdst = addr6-\u003es6_addr32[3];\n \t\t\t}\n \t\t\tneigh_release(neigh);\n-\t\t\tif (do_tx_error_icmp)\n+\t\t\tif (do_tx_error_icmp) {\n+\t\t\t\treason = SKB_DROP_REASON_NO_TX_TARGET;\n \t\t\t\tgoto tx_error_icmp;\n+\t\t\t}\n \t\t}\n #endif\n \t\telse\n@@ -763,8 +794,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\t\t    tunnel-\u003enet, READ_ONCE(tunnel-\u003eparms.link),\n \t\t\t    tunnel-\u003efwmark, skb_get_hash(skb), 0);\n \n-\tif (ip_tunnel_encap(skb, \u0026tunnel-\u003eencap, \u0026protocol, \u0026fl4) \u003c 0)\n+\tif (ip_tunnel_encap(skb, \u0026tunnel-\u003eencap, \u0026protocol, \u0026fl4) \u003c 0) {\n+\t\treason = SKB_DROP_REASON_TNL_ENCAP;\n \t\tgoto tx_error;\n+\t}\n \n \tif (connected \u0026\u0026 md) {\n \t\tuse_cache = ip_tunnel_dst_cache_usable(skb, tun_info);\n@@ -781,6 +814,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \t\tif (IS_ERR(rt)) {\n \t\t\tDEV_STATS_INC(dev, tx_carrier_errors);\n+\t\t\treason = SKB_DROP_REASON_IP_OUTNOROUTES;\n \t\t\tgoto tx_error;\n \t\t}\n \t\tif (use_cache)\n@@ -794,6 +828,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \tif (rt-\u003edst.dev == dev) {\n \t\tip_rt_put(rt);\n \t\tDEV_STATS_INC(dev, collisions);\n+\t\treason = SKB_DROP_REASON_RECURSION_LIMIT;\n \t\tgoto tx_error;\n \t}\n \n@@ -803,6 +838,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \tif (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) {\n \t\tip_rt_put(rt);\n+\t\treason = SKB_DROP_REASON_PKT_TOO_BIG;\n \t\tgoto tx_error;\n \t}\n \n@@ -837,7 +873,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n \tif (skb_cow_head(skb, max_headroom)) {\n \t\tip_rt_put(rt);\n \t\tDEV_STATS_INC(dev, tx_dropped);\n-\t\tkfree_skb(skb);\n+\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);\n \t\treturn;\n \t}\n \n@@ -853,7 +889,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n #endif\n tx_error:\n \tDEV_STATS_INC(dev, tx_errors);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n }\n EXPORT_SYMBOL_GPL(ip_tunnel_xmit);\n \ndiff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c\nindex 8ebda0b6a78b2..a510be5ad702f 100644\n--- a/net/ipv6/ip6_gre.c\n+++ b/net/ipv6/ip6_gre.c\n@@ -454,7 +454,8 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,\n \treturn 0;\n }\n \n-static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)\n+static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,\n+\t\t      enum skb_drop_reason *reason)\n {\n \tconst struct ipv6hdr *ipv6h;\n \tstruct ip6_tnl *tunnel;\n@@ -473,8 +474,10 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)\n \t\t\ttun_id = key32_to_tunnel_id(tpi-\u003ekey);\n \n \t\t\ttun_dst = ipv6_tun_rx_dst(skb, flags, tun_id, 0);\n-\t\t\tif (!tun_dst)\n+\t\t\tif (!tun_dst) {\n+\t\t\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\t\t\treturn PACKET_REJECT;\n+\t\t\t}\n \n \t\t\tip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);\n \t\t} else {\n@@ -484,12 +487,14 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)\n \t\treturn PACKET_RCVD;\n \t}\n \n+\t*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;\n \treturn PACKET_REJECT;\n }\n \n static int ip6erspan_rcv(struct sk_buff *skb,\n \t\t\t struct tnl_ptk_info *tpi,\n-\t\t\t int gre_hdr_len)\n+\t\t\t int gre_hdr_len,\n+\t\t\t enum skb_drop_reason *reason)\n {\n \tstruct erspan_base_hdr *ershdr;\n \tconst struct ipv6hdr *ipv6h;\n@@ -497,8 +502,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,\n \tstruct ip6_tnl *tunnel;\n \tu8 ver;\n \n-\tif (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))\n+\tif (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) {\n+\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\treturn PACKET_REJECT;\n+\t}\n \n \tipv6h = ipv6_hdr(skb);\n \tershdr = (struct erspan_base_hdr *)skb-\u003edata;\n@@ -510,13 +517,17 @@ static int ip6erspan_rcv(struct sk_buff *skb,\n \tif (tunnel) {\n \t\tint len = erspan_hdr_len(ver);\n \n-\t\tif (unlikely(!pskb_may_pull(skb, len)))\n+\t\tif (unlikely(!pskb_may_pull(skb, len))) {\n+\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\t\treturn PACKET_REJECT;\n+\t\t}\n \n \t\tif (__iptunnel_pull_header(skb, len,\n \t\t\t\t\t   htons(ETH_P_TEB),\n-\t\t\t\t\t   false, false) \u003c 0)\n+\t\t\t\t\t   false, false) \u003c 0) {\n+\t\t\t*reason = SKB_DROP_REASON_HDR_TRUNC;\n \t\t\treturn PACKET_REJECT;\n+\t\t}\n \n \t\tif (tunnel-\u003eparms.collect_md) {\n \t\t\tstruct erspan_metadata *pkt_md, *md;\n@@ -532,8 +543,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,\n \n \t\t\ttun_dst = ipv6_tun_rx_dst(skb, flags, tun_id,\n \t\t\t\t\t\t  sizeof(*md));\n-\t\t\tif (!tun_dst)\n+\t\t\tif (!tun_dst) {\n+\t\t\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\t\t\treturn PACKET_REJECT;\n+\t\t\t}\n \n \t\t\t/* MUST set options_len before referencing options */\n \t\t\tinfo = \u0026tun_dst-\u003eu.tun_info;\n@@ -564,37 +577,40 @@ static int ip6erspan_rcv(struct sk_buff *skb,\n \t\treturn PACKET_RCVD;\n \t}\n \n+\t*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;\n \treturn PACKET_REJECT;\n }\n \n static int gre_rcv(struct sk_buff *skb)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct tnl_ptk_info tpi;\n-\tbool csum_err = false;\n \tint hdr_len;\n \n-\thdr_len = gre_parse_header(skb, \u0026tpi, \u0026csum_err, htons(ETH_P_IPV6), 0);\n+\thdr_len = gre_parse_header(skb, \u0026tpi, \u0026reason, htons(ETH_P_IPV6), 0);\n \tif (hdr_len \u003c 0)\n \t\tgoto drop;\n \n-\tif (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))\n+\tif (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) {\n+\t\treason = SKB_DROP_REASON_HDR_TRUNC;\n \t\tgoto drop;\n+\t}\n \n \tif (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||\n \t\t     tpi.proto == htons(ETH_P_ERSPAN2))) {\n-\t\tif (ip6erspan_rcv(skb, \u0026tpi, hdr_len) == PACKET_RCVD)\n+\t\tif (ip6erspan_rcv(skb, \u0026tpi, hdr_len, \u0026reason) == PACKET_RCVD)\n \t\t\treturn 0;\n \t\tgoto out;\n \t}\n \n-\tif (ip6gre_rcv(skb, \u0026tpi) == PACKET_RCVD)\n+\tif (ip6gre_rcv(skb, \u0026tpi, \u0026reason) == PACKET_RCVD)\n \t\treturn 0;\n \n out:\n \ticmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);\n drop:\n \tdev_core_stats_rx_dropped_inc(skb-\u003edev);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn 0;\n }\n \n@@ -718,7 +734,8 @@ static struct ip_tunnel_info *skb_tunnel_info_txcheck(struct sk_buff *skb)\n static netdev_tx_t __gre6_xmit(struct sk_buff *skb,\n \t\t\t       struct net_device *dev, __u8 dsfield,\n \t\t\t       struct flowi6 *fl6, int encap_limit,\n-\t\t\t       __u32 *pmtu, __be16 proto)\n+\t\t\t       __u32 *pmtu, __be16 proto,\n+\t\t\t       enum skb_drop_reason *reason)\n {\n \tstruct ip6_tnl *tunnel = netdev_priv(dev);\n \tIP_TUNNEL_DECLARE_FLAGS(flags);\n@@ -742,8 +759,10 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,\n \n \t\ttun_info = skb_tunnel_info_txcheck(skb);\n \t\tif (IS_ERR(tun_info) ||\n-\t\t    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6))\n+\t\t    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6)) {\n+\t\t\t*reason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\t\treturn -EINVAL;\n+\t\t}\n \n \t\tkey = \u0026tun_info-\u003ekey;\n \t\tmemset(fl6, 0, sizeof(*fl6));\n@@ -761,8 +780,11 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,\n \t\tip_tunnel_flags_and(flags, flags, key-\u003etun_flags);\n \t\ttun_hlen = gre_calc_hlen(flags);\n \n-\t\tif (skb_cow_head(skb, dev-\u003eneeded_headroom ?: tun_hlen + tunnel-\u003eencap_hlen))\n+\t\tif (skb_cow_head(skb, dev-\u003eneeded_headroom ?:\n+\t\t\t\t tun_hlen + tunnel-\u003eencap_hlen)) {\n+\t\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\t\treturn -ENOMEM;\n+\t\t}\n \n \t\tgre_build_header(skb, tun_hlen,\n \t\t\t\t flags, protocol,\n@@ -772,8 +794,10 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,\n \t\t\t\t 0);\n \n \t} else {\n-\t\tif (skb_cow_head(skb, dev-\u003eneeded_headroom ?: tunnel-\u003ehlen))\n+\t\tif (skb_cow_head(skb, dev-\u003eneeded_headroom ?: tunnel-\u003ehlen)) {\n+\t\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\t\treturn -ENOMEM;\n+\t\t}\n \n \t\tip_tunnel_flags_copy(flags, tunnel-\u003eparms.o_flags);\n \n@@ -785,10 +809,11 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,\n \t}\n \n \treturn ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu,\n-\t\t\t    NEXTHDR_GRE);\n+\t\t\t    NEXTHDR_GRE, reason);\n }\n \n-static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)\n+static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev,\n+\t\t\t\t   enum skb_drop_reason *reason)\n {\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \tint encap_limit = -1;\n@@ -805,11 +830,13 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)\n \n \terr = gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,\n \t\t\t\t\t\tt-\u003eparms.o_flags));\n-\tif (err)\n+\tif (err) {\n+\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\treturn -1;\n+\t}\n \n \terr = __gre6_xmit(skb, dev, dsfield, \u0026fl6, encap_limit, \u0026mtu,\n-\t\t\t  skb-\u003eprotocol);\n+\t\t\t  skb-\u003eprotocol, reason);\n \tif (err != 0) {\n \t\t/* XXX: send ICMP error even if DF is not set. */\n \t\tif (err == -EMSGSIZE)\n@@ -821,7 +848,8 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)\n \treturn 0;\n }\n \n-static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)\n+static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev,\n+\t\t\t\t   enum skb_drop_reason *reason)\n {\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \tstruct ipv6hdr *ipv6h = ipv6_hdr(skb);\n@@ -831,19 +859,25 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)\n \t__u32 mtu;\n \tint err;\n \n-\tif (ipv6_addr_equal(\u0026t-\u003eparms.raddr, \u0026ipv6h-\u003esaddr))\n+\tif (ipv6_addr_equal(\u0026t-\u003eparms.raddr, \u0026ipv6h-\u003esaddr)) {\n+\t\t*reason = SKB_DROP_REASON_RECURSION_LIMIT;\n \t\treturn -1;\n+\t}\n \n \tif (!t-\u003eparms.collect_md \u0026\u0026\n-\t    prepare_ip6gre_xmit_ipv6(skb, dev, \u0026fl6, \u0026dsfield, \u0026encap_limit))\n+\t    prepare_ip6gre_xmit_ipv6(skb, dev, \u0026fl6, \u0026dsfield, \u0026encap_limit)) {\n+\t\t*reason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;\n \t\treturn -1;\n+\t}\n \n \tif (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,\n-\t\t\t\t\t      t-\u003eparms.o_flags)))\n+\t\t\t\t\t      t-\u003eparms.o_flags))) {\n+\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\treturn -1;\n+\t}\n \n \terr = __gre6_xmit(skb, dev, dsfield, \u0026fl6, encap_limit,\n-\t\t\t  \u0026mtu, skb-\u003eprotocol);\n+\t\t\t  \u0026mtu, skb-\u003eprotocol, reason);\n \tif (err != 0) {\n \t\tif (err == -EMSGSIZE)\n \t\t\ticmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);\n@@ -853,7 +887,8 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)\n \treturn 0;\n }\n \n-static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev)\n+static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev,\n+\t\t\t     enum skb_drop_reason *reason)\n {\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \tint encap_limit = -1;\n@@ -863,14 +898,19 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev)\n \tint err;\n \n \tif (!t-\u003eparms.collect_md \u0026\u0026\n-\t    prepare_ip6gre_xmit_other(skb, dev, \u0026fl6, \u0026dsfield, \u0026encap_limit))\n+\t    prepare_ip6gre_xmit_other(skb, dev, \u0026fl6, \u0026dsfield, \u0026encap_limit)) {\n+\t\t*reason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;\n \t\treturn -1;\n+\t}\n \n \terr = gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,\n \t\t\t\t\t\tt-\u003eparms.o_flags));\n-\tif (err)\n+\tif (err) {\n+\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\treturn err;\n-\terr = __gre6_xmit(skb, dev, dsfield, \u0026fl6, encap_limit, \u0026mtu, skb-\u003eprotocol);\n+\t}\n+\terr = __gre6_xmit(skb, dev, dsfield, \u0026fl6, encap_limit, \u0026mtu,\n+\t\t\t  skb-\u003eprotocol, reason);\n \n \treturn err;\n }\n@@ -878,16 +918,20 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev)\n static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,\n \tstruct net_device *dev)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel_info *tun_info = NULL;\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \t__be16 payload_protocol;\n \tint ret;\n \n-\tif (!pskb_inet_may_pull(skb))\n+\treason = pskb_inet_may_pull_reason(skb);\n+\tif (reason)\n \t\tgoto tx_err;\n \n-\tif (!ip6_tnl_xmit_ctl(t, \u0026t-\u003eparms.laddr, \u0026t-\u003eparms.raddr))\n+\tif (!ip6_tnl_xmit_ctl(t, \u0026t-\u003eparms.laddr, \u0026t-\u003eparms.raddr)) {\n+\t\treason = SKB_DROP_REASON_DEV_READY;\n \t\tgoto tx_err;\n+\t}\n \n \tif (t-\u003eparms.collect_md)\n \t\ttun_info = skb_tunnel_info_txcheck(skb);\n@@ -895,13 +939,13 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,\n \tpayload_protocol = skb_protocol(skb, true);\n \tswitch (payload_protocol) {\n \tcase htons(ETH_P_IP):\n-\t\tret = ip6gre_xmit_ipv4(skb, dev);\n+\t\tret = ip6gre_xmit_ipv4(skb, dev, \u0026reason);\n \t\tbreak;\n \tcase htons(ETH_P_IPV6):\n-\t\tret = ip6gre_xmit_ipv6(skb, dev);\n+\t\tret = ip6gre_xmit_ipv6(skb, dev, \u0026reason);\n \t\tbreak;\n \tdefault:\n-\t\tret = ip6gre_xmit_other(skb, dev);\n+\t\tret = ip6gre_xmit_other(skb, dev, \u0026reason);\n \t\tbreak;\n \t}\n \n@@ -914,13 +958,14 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,\n \tif (!IS_ERR(tun_info))\n \t\tDEV_STATS_INC(dev, tx_errors);\n \tDEV_STATS_INC(dev, tx_dropped);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn NETDEV_TX_OK;\n }\n \n static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \t\t\t\t\t struct net_device *dev)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip_tunnel_info *tun_info = NULL;\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \tstruct dst_entry *dst = skb_dst(skb);\n@@ -934,18 +979,25 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \t__u32 mtu;\n \tint nhoff;\n \n-\tif (!pskb_inet_may_pull(skb))\n+\treason = pskb_inet_may_pull_reason(skb);\n+\tif (reason)\n \t\tgoto tx_err;\n \n-\tif (!ip6_tnl_xmit_ctl(t, \u0026t-\u003eparms.laddr, \u0026t-\u003eparms.raddr))\n+\tif (!ip6_tnl_xmit_ctl(t, \u0026t-\u003eparms.laddr, \u0026t-\u003eparms.raddr)) {\n+\t\treason = SKB_DROP_REASON_DEV_READY;\n \t\tgoto tx_err;\n+\t}\n \n-\tif (gre_handle_offloads(skb, false))\n+\tif (gre_handle_offloads(skb, false)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto tx_err;\n+\t}\n \n \tif (skb-\u003elen \u003e dev-\u003emtu + dev-\u003ehard_header_len) {\n-\t\tif (pskb_trim(skb, dev-\u003emtu + dev-\u003ehard_header_len))\n+\t\tif (pskb_trim(skb, dev-\u003emtu + dev-\u003ehard_header_len)) {\n+\t\t\treason = SKB_DROP_REASON_NOMEM;\n \t\t\tgoto tx_err;\n+\t\t}\n \t\ttruncate = true;\n \t}\n \n@@ -965,8 +1017,10 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \t\t\ttruncate = true;\n \t}\n \n-\tif (skb_cow_head(skb, dev-\u003eneeded_headroom ?: t-\u003ehlen))\n+\tif (skb_cow_head(skb, dev-\u003eneeded_headroom ?: t-\u003ehlen)) {\n+\t\treason = SKB_DROP_REASON_NOMEM;\n \t\tgoto tx_err;\n+\t}\n \n \tIPCB(skb)-\u003eflags = 0;\n \n@@ -980,8 +1034,10 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \n \t\ttun_info = skb_tunnel_info_txcheck(skb);\n \t\tif (IS_ERR(tun_info) ||\n-\t\t    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6))\n+\t\t    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6)) {\n+\t\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\t\tgoto tx_err;\n+\t\t}\n \n \t\tkey = \u0026tun_info-\u003ekey;\n \t\tmemset(\u0026fl6, 0, sizeof(fl6));\n@@ -993,10 +1049,14 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \n \t\tdsfield = key-\u003etos;\n \t\tif (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT,\n-\t\t\t      tun_info-\u003ekey.tun_flags))\n+\t\t\t      tun_info-\u003ekey.tun_flags)) {\n+\t\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\t\tgoto tx_err;\n-\t\tif (tun_info-\u003eoptions_len \u003c sizeof(*md))\n+\t\t}\n+\t\tif (tun_info-\u003eoptions_len \u003c sizeof(*md)) {\n+\t\t\treason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\t\tgoto tx_err;\n+\t\t}\n \t\tmd = ip_tunnel_info_opts(tun_info);\n \n \t\ttun_id = tunnel_id_to_key32(key-\u003etun_id);\n@@ -1014,6 +1074,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \t\t\t\t\t       truncate, false);\n \t\t\tproto = htons(ETH_P_ERSPAN2);\n \t\t} else {\n+\t\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\t\tgoto tx_err;\n \t\t}\n \t} else {\n@@ -1024,11 +1085,16 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \t\t\t\t\t\t \u0026dsfield, \u0026encap_limit);\n \t\t\tbreak;\n \t\tcase htons(ETH_P_IPV6):\n-\t\t\tif (ipv6_addr_equal(\u0026t-\u003eparms.raddr, \u0026ipv6_hdr(skb)-\u003esaddr))\n+\t\t\tif (ipv6_addr_equal(\u0026t-\u003eparms.raddr,\n+\t\t\t\t\t    \u0026ipv6_hdr(skb)-\u003esaddr)) {\n+\t\t\t\treason = SKB_DROP_REASON_RECURSION_LIMIT;\n \t\t\t\tgoto tx_err;\n+\t\t\t}\n \t\t\tif (prepare_ip6gre_xmit_ipv6(skb, dev, \u0026fl6,\n-\t\t\t\t\t\t     \u0026dsfield, \u0026encap_limit))\n+\t\t\t\t\t\t     \u0026dsfield, \u0026encap_limit)) {\n+\t\t\t\treason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;\n \t\t\t\tgoto tx_err;\n+\t\t\t}\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tmemcpy(\u0026fl6, \u0026t-\u003efl.u.ip6, sizeof(fl6));\n@@ -1047,6 +1113,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \t\t\t\t\t       truncate, false);\n \t\t\tproto = htons(ETH_P_ERSPAN2);\n \t\t} else {\n+\t\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\t\tgoto tx_err;\n \t\t}\n \n@@ -1065,7 +1132,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \t\t\tdst-\u003eops-\u003eupdate_pmtu(dst, NULL, skb, mtu, false);\n \t}\n \terr = ip6_tnl_xmit(skb, dev, dsfield, \u0026fl6, encap_limit, \u0026mtu,\n-\t\t\t   NEXTHDR_GRE);\n+\t\t\t   NEXTHDR_GRE, \u0026reason);\n \tif (err != 0) {\n \t\t/* XXX: send ICMP error even if DF is not set. */\n \t\tif (err == -EMSGSIZE) {\n@@ -1084,7 +1151,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n \tif (!IS_ERR(tun_info))\n \t\tDEV_STATS_INC(dev, tx_errors);\n \tDEV_STATS_INC(dev, tx_dropped);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn NETDEV_TX_OK;\n }\n \ndiff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c\nindex d5ff50a2ac017..d804c67c4be3b 100644\n--- a/net/ipv6/ip6_tunnel.c\n+++ b/net/ipv6/ip6_tunnel.c\n@@ -813,6 +813,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n \t\t\t\t\t\tstruct sk_buff *skb),\n \t\t\t bool log_ecn_err)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tconst struct ipv6hdr *ipv6h;\n \tint nh, err;\n \n@@ -820,15 +821,22 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n \t    test_bit(IP_TUNNEL_CSUM_BIT, tpi-\u003eflags)) {\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_crc_errors);\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\treason = SKB_DROP_REASON_TNL_OPT_MISMATCH;\n \t\tgoto drop;\n \t}\n \n \tif (test_bit(IP_TUNNEL_SEQ_BIT, tunnel-\u003eparms.i_flags)) {\n-\t\tif (!test_bit(IP_TUNNEL_SEQ_BIT, tpi-\u003eflags) ||\n-\t\t    (tunnel-\u003ei_seqno \u0026\u0026\n-\t\t     (s32)(ntohl(tpi-\u003eseq) - tunnel-\u003ei_seqno) \u003c 0)) {\n+\t\tif (!test_bit(IP_TUNNEL_SEQ_BIT, tpi-\u003eflags)) {\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_fifo_errors);\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\t\treason = SKB_DROP_REASON_TNL_OPT_MISMATCH;\n+\t\t\tgoto drop;\n+\t\t}\n+\t\tif (tunnel-\u003ei_seqno \u0026\u0026\n+\t\t    (s32)(ntohl(tpi-\u003eseq) - tunnel-\u003ei_seqno) \u003c 0) {\n+\t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_fifo_errors);\n+\t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\t\treason = SKB_DROP_REASON_TNL_OLD_SEQ;\n \t\t\tgoto drop;\n \t\t}\n \t\ttunnel-\u003ei_seqno = ntohl(tpi-\u003eseq) + 1;\n@@ -838,7 +846,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n \n \t/* Warning: All skb pointers will be invalidated! */\n \tif (tunnel-\u003edev-\u003etype == ARPHRD_ETHER) {\n-\t\tif (!pskb_may_pull(skb, ETH_HLEN)) {\n+\t\treason = pskb_may_pull_reason(skb, ETH_HLEN);\n+\t\tif (reason) {\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_length_errors);\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n \t\t\tgoto drop;\n@@ -859,7 +868,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n \n \tskb_reset_network_header(skb);\n \n-\tif (skb_vlan_inet_prepare(skb, true)) {\n+\treason = skb_vlan_inet_prepare(skb, true);\n+\tif (reason) {\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_length_errors);\n \t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n \t\tgoto drop;\n@@ -881,6 +891,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n \t\tif (err \u003e 1) {\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_frame_errors);\n \t\t\tDEV_STATS_INC(tunnel-\u003edev, rx_errors);\n+\t\t\treason = SKB_DROP_REASON_IP_TUNNEL_ECN;\n \t\t\tgoto drop;\n \t\t}\n \t}\n@@ -898,7 +909,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n drop:\n \tif (tun_dst)\n \t\tdst_release((struct dst_entry *)tun_dst);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn 0;\n }\n \n@@ -1086,6 +1097,7 @@ EXPORT_SYMBOL_GPL(ip6_tnl_xmit_ctl);\n  *   @encap_limit: encapsulation limit\n  *   @pmtu: Path MTU is stored if packet is too big\n  *   @proto: next header value\n+ *   @reason: drop reason, only written when the packet is dropped\n  *\n  * Description:\n  *   Build new header and do some sanity checks on the packet before sending\n@@ -1099,7 +1111,7 @@ EXPORT_SYMBOL_GPL(ip6_tnl_xmit_ctl);\n \n int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \t\t struct flowi6 *fl6, int encap_limit, __u32 *pmtu,\n-\t\t __u8 proto)\n+\t\t __u8 proto, enum skb_drop_reason *reason)\n {\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \tstruct net *net = t-\u003enet;\n@@ -1132,13 +1144,17 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \t\t\tstruct neighbour *neigh;\n \t\t\tint addr_type;\n \n-\t\t\tif (!skb_dst(skb))\n+\t\t\tif (!skb_dst(skb)) {\n+\t\t\t\t*reason = SKB_DROP_REASON_NO_TX_TARGET;\n \t\t\t\tgoto tx_err_link_failure;\n+\t\t\t}\n \n \t\t\tneigh = dst_neigh_lookup(skb_dst(skb),\n \t\t\t\t\t\t \u0026ipv6_hdr(skb)-\u003edaddr);\n-\t\t\tif (!neigh)\n+\t\t\tif (!neigh) {\n+\t\t\t\t*reason = SKB_DROP_REASON_NEIGH_CREATEFAIL;\n \t\t\t\tgoto tx_err_link_failure;\n+\t\t\t}\n \n \t\t\taddr6 = (struct in6_addr *)\u0026neigh-\u003eprimary_key;\n \t\t\taddr_type = ipv6_addr_type(addr6);\n@@ -1151,8 +1167,10 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \t\t} else if (payload_protocol == htons(ETH_P_IP)) {\n \t\t\tconst struct rtable *rt = skb_rtable(skb);\n \n-\t\t\tif (!rt)\n+\t\t\tif (!rt) {\n+\t\t\t\t*reason = SKB_DROP_REASON_IP_OUTNOROUTES;\n \t\t\t\tgoto tx_err_link_failure;\n+\t\t\t}\n \n \t\t\tif (rt-\u003ert_gw_family == AF_INET6)\n \t\t\t\tmemcpy(\u0026fl6-\u003edaddr, \u0026rt-\u003ert_gw6, sizeof(fl6-\u003edaddr));\n@@ -1169,8 +1187,10 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \tif (use_cache)\n \t\tdst = dst_cache_get(\u0026t-\u003edst_cache);\n \n-\tif (!ip6_tnl_xmit_ctl(t, \u0026fl6-\u003esaddr, \u0026fl6-\u003edaddr))\n+\tif (!ip6_tnl_xmit_ctl(t, \u0026fl6-\u003esaddr, \u0026fl6-\u003edaddr)) {\n+\t\t*reason = SKB_DROP_REASON_DEV_READY;\n \t\tgoto tx_err_link_failure;\n+\t}\n \n \tif (!dst) {\n route_lookup:\n@@ -1179,18 +1199,23 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \n \t\tdst = ip6_route_output(net, NULL, fl6);\n \n-\t\tif (dst-\u003eerror)\n+\t\tif (dst-\u003eerror) {\n+\t\t\t*reason = SKB_DROP_REASON_IP_OUTNOROUTES;\n \t\t\tgoto tx_err_link_failure;\n+\t\t}\n \t\tdst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0);\n \t\tif (IS_ERR(dst)) {\n \t\t\terr = PTR_ERR(dst);\n \t\t\tdst = NULL;\n+\t\t\t*reason = SKB_DROP_REASON_IP_OUTNOROUTES;\n \t\t\tgoto tx_err_link_failure;\n \t\t}\n \t\tif (t-\u003eparms.collect_md \u0026\u0026 ipv6_addr_any(\u0026fl6-\u003esaddr) \u0026\u0026\n \t\t    ipv6_dev_get_saddr(net, ip6_dst_idev(dst)-\u003edev,\n-\t\t\t\t       \u0026fl6-\u003edaddr, 0, \u0026fl6-\u003esaddr))\n+\t\t\t\t       \u0026fl6-\u003edaddr, 0, \u0026fl6-\u003esaddr)) {\n+\t\t\t*reason = SKB_DROP_REASON_NO_TX_TARGET;\n \t\t\tgoto tx_err_link_failure;\n+\t\t}\n \t\tndst = dst;\n \t}\n \n@@ -1200,6 +1225,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \t\tDEV_STATS_INC(dev, collisions);\n \t\tnet_warn_ratelimited(\"%s: Local routing loop detected!\\n\",\n \t\t\t\t     t-\u003eparms.name);\n+\t\t*reason = SKB_DROP_REASON_RECURSION_LIMIT;\n \t\tgoto tx_err_dst_release;\n \t}\n \tmtu = dst6_mtu(dst) - eth_hlen - psh_hlen - t-\u003etun_hlen;\n@@ -1214,6 +1240,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \tif (skb-\u003elen - t-\u003etun_hlen - eth_hlen \u003e mtu \u0026\u0026 !skb_is_gso(skb)) {\n \t\t*pmtu = mtu;\n \t\terr = -EMSGSIZE;\n+\t\t*reason = SKB_DROP_REASON_PKT_TOO_BIG;\n \t\tgoto tx_err_dst_release;\n \t}\n \n@@ -1236,12 +1263,16 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \t */\n \tmax_headroom += LL_RESERVED_SPACE(tdev);\n \n-\tif (skb_cow_head(skb, max_headroom))\n+\tif (skb_cow_head(skb, max_headroom)) {\n+\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\tgoto tx_err_dst_release;\n+\t}\n \n \tif (t-\u003eparms.collect_md) {\n-\t\tif (t-\u003eencap.type != TUNNEL_ENCAP_NONE)\n+\t\tif (t-\u003eencap.type != TUNNEL_ENCAP_NONE) {\n+\t\t\t*reason = SKB_DROP_REASON_TNL_ENCAP;\n \t\t\tgoto tx_err_dst_release;\n+\t\t}\n \t} else {\n \t\tif (use_cache \u0026\u0026 ndst)\n \t\t\tdst_cache_set_ip6(\u0026t-\u003edst_cache, ndst, \u0026fl6-\u003esaddr);\n@@ -1265,8 +1296,10 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\n \tip_tunnel_adj_headroom(dev, max_headroom);\n \n \terr = ip6_tnl_encap(skb, t, \u0026proto, fl6);\n-\tif (err)\n+\tif (err) {\n+\t\t*reason = SKB_DROP_REASON_TNL_ENCAP;\n \t\treturn err;\n+\t}\n \n \tif (encap_limit \u003e= 0) {\n \t\tinit_tel_txopt(\u0026opt, encap_limit);\n@@ -1295,7 +1328,7 @@ EXPORT_SYMBOL(ip6_tnl_xmit);\n \n static inline int\n ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\n-\t\tu8 protocol)\n+\t\tu8 protocol, enum skb_drop_reason *reason)\n {\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \tstruct ipv6hdr *ipv6h;\n@@ -1309,8 +1342,10 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\n \tint err;\n \n \ttproto = READ_ONCE(t-\u003eparms.proto);\n-\tif (tproto != protocol \u0026\u0026 tproto != 0)\n+\tif (tproto != protocol \u0026\u0026 tproto != 0) {\n+\t\t*reason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\treturn -1;\n+\t}\n \n \tif (t-\u003eparms.collect_md) {\n \t\tstruct ip_tunnel_info *tun_info;\n@@ -1318,8 +1353,10 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \t\ttun_info = skb_tunnel_info(skb);\n \t\tif (unlikely(!tun_info || !(tun_info-\u003emode \u0026 IP_TUNNEL_INFO_TX) ||\n-\t\t\t     ip_tunnel_info_af(tun_info) != AF_INET6))\n+\t\t\t     ip_tunnel_info_af(tun_info) != AF_INET6)) {\n+\t\t\t*reason = SKB_DROP_REASON_TUNNEL_TXINFO;\n \t\t\treturn -1;\n+\t\t}\n \t\tkey = \u0026tun_info-\u003ekey;\n \t\tmemset(\u0026fl6, 0, sizeof(fl6));\n \t\tfl6.flowi6_proto = protocol;\n@@ -1356,6 +1393,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\t\t\tif (tel-\u003eencap_limit == 0) {\n \t\t\t\t\ticmpv6_ndo_send(skb, ICMPV6_PARAMPROB,\n \t\t\t\t\t\t\tICMPV6_HDR_FIELD, offset + 2);\n+\t\t\t\t\t*reason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;\n \t\t\t\t\treturn -1;\n \t\t\t\t}\n \t\t\t\tencap_limit = tel-\u003eencap_limit - 1;\n@@ -1397,13 +1435,15 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\n \tfl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);\n \tdsfield = INET_ECN_encapsulate(dsfield, orig_dsfield);\n \n-\tif (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))\n+\tif (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) {\n+\t\t*reason = SKB_DROP_REASON_NOMEM;\n \t\treturn -1;\n+\t}\n \n \tskb_set_inner_ipproto(skb, protocol);\n \n \terr = ip6_tnl_xmit(skb, dev, dsfield, \u0026fl6, encap_limit, \u0026mtu,\n-\t\t\t   protocol);\n+\t\t\t   protocol, reason);\n \tif (err != 0) {\n \t\t/* XXX: send ICMP error even if DF is not set. */\n \t\tif (err == -EMSGSIZE)\n@@ -1418,6 +1458,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\n \t\t\tdefault:\n \t\t\t\tbreak;\n \t\t\t}\n+\t\t*reason = SKB_DROP_REASON_PKT_TOO_BIG;\n \t\treturn -1;\n \t}\n \n@@ -1427,11 +1468,13 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\n static netdev_tx_t\n ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)\n {\n+\tenum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;\n \tstruct ip6_tnl *t = netdev_priv(dev);\n \tu8 ipproto;\n \tint ret;\n \n-\tif (!pskb_inet_may_pull(skb))\n+\treason = pskb_inet_may_pull_reason(skb);\n+\tif (reason)\n \t\tgoto tx_err;\n \n \tswitch (skb-\u003eprotocol) {\n@@ -1439,18 +1482,21 @@ ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\tipproto = IPPROTO_IPIP;\n \t\tbreak;\n \tcase htons(ETH_P_IPV6):\n-\t\tif (ip6_tnl_addr_conflict(t, ipv6_hdr(skb)))\n+\t\tif (ip6_tnl_addr_conflict(t, ipv6_hdr(skb))) {\n+\t\t\treason = SKB_DROP_REASON_RECURSION_LIMIT;\n \t\t\tgoto tx_err;\n+\t\t}\n \t\tipproto = IPPROTO_IPV6;\n \t\tbreak;\n \tcase htons(ETH_P_MPLS_UC):\n \t\tipproto = IPPROTO_MPLS;\n \t\tbreak;\n \tdefault:\n+\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n \t\tgoto tx_err;\n \t}\n \n-\tret = ipxip6_tnl_xmit(skb, dev, ipproto);\n+\tret = ipxip6_tnl_xmit(skb, dev, ipproto, \u0026reason);\n \tif (ret \u003c 0)\n \t\tgoto tx_err;\n \n@@ -1459,7 +1505,7 @@ ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)\n tx_err:\n \tDEV_STATS_INC(dev, tx_errors);\n \tDEV_STATS_INC(dev, tx_dropped);\n-\tkfree_skb(skb);\n+\tkfree_skb_reason(skb, reason);\n \treturn NETDEV_TX_OK;\n }\n \n"
}

2/1 2026/09/13 04:15 agent patch-evaluator
1m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch series purely annotates existing packet drop points in IPv4/IPv6 GRE and IP tunneling code with specific enum skb_drop_reason values passed to kfree_skb_reason(). This enriches the kfree_skb tracepoint without altering control flow, packet acceptance/rejection decisions, or kernel data structures. As purely tracepoint-related annotation changes that do not modify executable logic or invariants, fuzzing is not warranted.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 40bd7d2fc591a6070762fa2effffbe26cab83dd8
Author: syz-cluster <triage@syzkaller.com>
Date:   Sun Sep 13 04:15:35 2026 +0000

    syz-cluster: applied patch under review

diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index 12f9096515912..30378a0d22726 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -129,6 +129,12 @@
 	FN(PSP_INPUT)			\
 	FN(PSP_OUTPUT)			\
 	FN(RECURSION_LIMIT)		\
+	FN(TNL_OPT_MISMATCH)		\
+	FN(TNL_OLD_SEQ)			\
+	FN(GRE_INVALID_HDR)		\
+	FN(GRE_CSUM)			\
+	FN(GRE_TUNNEL_NOT_FOUND)	\
+	FN(TNL_ENCAP)			\
 	FNe(MAX)
 
 /**
@@ -612,6 +618,38 @@ enum skb_drop_reason {
 	SKB_DROP_REASON_PSP_OUTPUT,
 	/** @SKB_DROP_REASON_RECURSION_LIMIT: Dead loop on virtual device. */
 	SKB_DROP_REASON_RECURSION_LIMIT,
+	/**
+	 * @SKB_DROP_REASON_TNL_OPT_MISMATCH: the tunnel options
+	 * carried by the packet do not match the tunnel configuration, e.g.
+	 * a GRE tunnel configured with 'icsum' or 'iseq' received a packet
+	 * with no checksum or no sequence number.
+	 */
+	SKB_DROP_REASON_TNL_OPT_MISMATCH,
+	/**
+	 * @SKB_DROP_REASON_TNL_OLD_SEQ: the sequence number carried
+	 * by the packet is older than the one expected by the tunnel, e.g.
+	 * after the remote endpoint restarted and reset its sequence
+	 * numbering.
+	 */
+	SKB_DROP_REASON_TNL_OLD_SEQ,
+	/**
+	 * @SKB_DROP_REASON_GRE_INVALID_HDR: the GRE header is invalid, e.g.
+	 * an unsupported version or the routing bit is set.
+	 */
+	SKB_DROP_REASON_GRE_INVALID_HDR,
+	/** @SKB_DROP_REASON_GRE_CSUM: GRE checksum error */
+	SKB_DROP_REASON_GRE_CSUM,
+	/**
+	 * @SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND: no GRE tunnel found for the
+	 * endpoints and the key the packet carries.
+	 */
+	SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND,
+	/**
+	 * @SKB_DROP_REASON_TNL_ENCAP: failed to build the
+	 * encapsulation header of a tunnel, e.g. an unknown or
+	 * unregistered encapsulation type.
+	 */
+	SKB_DROP_REASON_TNL_ENCAP,
 	/**
 	 * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
 	 * shouldn't be used as a real 'reason' - only for tracing code gen
diff --git a/include/net/gre.h b/include/net/gre.h
index b55f67ecd2fc4..a63f26c3f78ed 100644
--- a/include/net/gre.h
+++ b/include/net/gre.h
@@ -33,7 +33,7 @@ int gre_add_protocol(const struct gre_protocol *proto, u8 version);
 int gre_del_protocol(const struct gre_protocol *proto, u8 version);
 
 int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
-		     bool *csum_err, __be16 proto, int nhs);
+		     enum skb_drop_reason *reason, __be16 proto, int nhs);
 
 static inline bool netif_is_gretap(const struct net_device *dev)
 {
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index b99805ee2fd14..95f6d12254df6 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -143,7 +143,8 @@ int ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
 int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
 		     const struct in6_addr *raddr);
 int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
-		 struct flowi6 *fl6, int encap_limit, __u32 *pmtu, __u8 proto);
+		 struct flowi6 *fl6, int encap_limit, __u32 *pmtu, __u8 proto,
+		 enum skb_drop_reason *reason);
 __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);
 __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
 			     const struct in6_addr *raddr);
diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c
index 96fd7dc6d82dd..efd5f60a9c591 100644
--- a/net/ipv4/gre_demux.c
+++ b/net/ipv4/gre_demux.c
@@ -58,26 +58,43 @@ EXPORT_SYMBOL_GPL(gre_del_protocol);
 
 /* Fills in tpi and returns header length to be pulled.
  * Note that caller must use pskb_may_pull() before pulling GRE header.
+ *
+ * @reason is only written when the header is rejected, so the caller has
+ * to initialise it before the call.
+ *
+ * A NULL @reason means that the caller is not interested in the drop
+ * reason, and also that the checksum must not be verified.  This is what
+ * the ICMP error handlers need, as they only get a part of the original
+ * packet.
  */
 int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
-		     bool *csum_err, __be16 proto, int nhs)
+		     enum skb_drop_reason *reason, __be16 proto, int nhs)
 {
 	const struct gre_base_hdr *greh;
 	__be32 *options;
 	int hdr_len;
 
-	if (unlikely(!pskb_may_pull(skb, nhs + sizeof(struct gre_base_hdr))))
+	if (unlikely(!pskb_may_pull(skb, nhs + sizeof(struct gre_base_hdr)))) {
+		if (reason)
+			*reason = SKB_DROP_REASON_HDR_TRUNC;
 		return -EINVAL;
+	}
 
 	greh = (struct gre_base_hdr *)(skb->data + nhs);
-	if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING)))
+	if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) {
+		if (reason)
+			*reason = SKB_DROP_REASON_GRE_INVALID_HDR;
 		return -EINVAL;
+	}
 
 	gre_flags_to_tnl_flags(tpi->flags, greh->flags);
 	hdr_len = gre_calc_hlen(tpi->flags);
 
-	if (!pskb_may_pull(skb, nhs + hdr_len))
+	if (!pskb_may_pull(skb, nhs + hdr_len)) {
+		if (reason)
+			*reason = SKB_DROP_REASON_HDR_TRUNC;
 		return -EINVAL;
+	}
 
 	greh = (struct gre_base_hdr *)(skb->data + nhs);
 	tpi->proto = greh->protocol;
@@ -87,8 +104,8 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 		if (!skb_checksum_simple_validate(skb)) {
 			skb_checksum_try_convert(skb, IPPROTO_GRE,
 						 null_compute_pseudo);
-		} else if (csum_err) {
-			*csum_err = true;
+		} else if (reason) {
+			*reason = SKB_DROP_REASON_GRE_CSUM;
 			return -EINVAL;
 		}
 
@@ -116,8 +133,11 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 
 		val = skb_header_pointer(skb, nhs + hdr_len,
 					 sizeof(_val), &_val);
-		if (!val)
+		if (!val) {
+			if (reason)
+				*reason = SKB_DROP_REASON_HDR_TRUNC;
 			return -EINVAL;
+		}
 		tpi->proto = proto;
 		if ((*val & 0xF0) != 0x40)
 			hdr_len += 4;
@@ -132,8 +152,11 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 	    greh->protocol == htons(ETH_P_ERSPAN2)) {
 		struct erspan_base_hdr *ershdr;
 
-		if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr)))
+		if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr))) {
+			if (reason)
+				*reason = SKB_DROP_REASON_HDR_TRUNC;
 			return -EINVAL;
+		}
 
 		ershdr = (struct erspan_base_hdr *)(skb->data + nhs + hdr_len);
 		tpi->key = cpu_to_be32(get_session_id(ershdr));
@@ -145,16 +168,20 @@ EXPORT_SYMBOL(gre_parse_header);
 
 static int gre_rcv(struct sk_buff *skb)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	const struct gre_protocol *proto;
 	u8 ver;
 	int ret;
 
-	if (!pskb_may_pull(skb, 12))
+	reason = pskb_may_pull_reason(skb, 12);
+	if (reason)
 		goto drop;
 
 	ver = skb->data[1]&0x7f;
-	if (ver >= GREPROTO_MAX)
+	if (ver >= GREPROTO_MAX) {
+		reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 		goto drop;
+	}
 
 	rcu_read_lock();
 	proto = rcu_dereference(gre_proto[ver]);
@@ -167,11 +194,11 @@ static int gre_rcv(struct sk_buff *skb)
 drop_nohandler:
 	rcu_read_unlock();
 	dev_core_stats_rx_nohandler_inc(skb->dev);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, SKB_DROP_REASON_UNHANDLED_PROTO);
 	return NET_RX_DROP;
 drop:
 	dev_core_stats_rx_dropped_inc(skb->dev);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return NET_RX_DROP;
 }
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 82309efd417e0..7b9687f1de0c4 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -265,7 +265,7 @@ static bool is_erspan_type1(int gre_hdr_len)
 }
 
 static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
-		      int gre_hdr_len)
+		      int gre_hdr_len, enum skb_drop_reason *reason)
 {
 	struct net *net = dev_net(skb->dev);
 	struct metadata_dst *tun_dst = NULL;
@@ -289,8 +289,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 					  iph->saddr, iph->daddr, 0);
 	} else {
 		if (unlikely(!pskb_may_pull(skb,
-					    gre_hdr_len + sizeof(*ershdr))))
+					    gre_hdr_len + sizeof(*ershdr)))) {
+			*reason = SKB_DROP_REASON_HDR_TRUNC;
 			return PACKET_REJECT;
+		}
 
 		ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
 		ver = ershdr->ver;
@@ -306,8 +308,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 		else
 			len = gre_hdr_len + erspan_hdr_len(ver);
 
-		if (unlikely(!pskb_may_pull(skb, len)))
+		if (unlikely(!pskb_may_pull(skb, len))) {
+			*reason = SKB_DROP_REASON_HDR_TRUNC;
 			return PACKET_REJECT;
+		}
 
 		if (__iptunnel_pull_header(skb,
 					   len,
@@ -327,8 +331,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 
 			tun_dst = ip_tun_rx_dst(skb, flags,
 						tun_id, sizeof(*md));
-			if (!tun_dst)
+			if (!tun_dst) {
+				*reason = SKB_DROP_REASON_NOMEM;
 				return PACKET_REJECT;
+			}
 
 			/* MUST set options_len before referencing options */
 			info = &tun_dst->u.tun_info;
@@ -356,15 +362,17 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
 		return PACKET_RCVD;
 	}
+	*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;
 	return PACKET_REJECT;
 
 drop:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, SKB_DROP_REASON_HDR_TRUNC);
 	return PACKET_RCVD;
 }
 
 static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
-		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
+		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto,
+		       enum skb_drop_reason *reason)
 {
 	struct metadata_dst *tun_dst = NULL;
 	const struct iphdr *iph;
@@ -400,22 +408,25 @@ static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
 
 			tun_id = key32_to_tunnel_id(tpi->key);
 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
-			if (!tun_dst)
+			if (!tun_dst) {
+				*reason = SKB_DROP_REASON_NOMEM;
 				return PACKET_REJECT;
+			}
 		}
 
 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
 		return PACKET_RCVD;
 	}
+	*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;
 	return PACKET_NEXT;
 
 drop:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, SKB_DROP_REASON_HDR_TRUNC);
 	return PACKET_RCVD;
 }
 
 static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
-		     int hdr_len)
+		     int hdr_len, enum skb_drop_reason *reason)
 {
 	struct net *net = dev_net(skb->dev);
 	struct ip_tunnel_net *itn;
@@ -426,21 +437,21 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
 	else
 		itn = net_generic(net, ipgre_net_id);
 
-	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
+	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false, reason);
 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
 		/* ipgre tunnels in collect metadata mode should receive
 		 * also ETH_P_TEB traffic.
 		 */
 		itn = net_generic(net, ipgre_net_id);
-		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
+		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true, reason);
 	}
 	return res;
 }
 
 static int gre_rcv(struct sk_buff *skb)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct tnl_ptk_info tpi;
-	bool csum_err = false;
 	int hdr_len;
 
 #ifdef CONFIG_NET_IPGRE_BROADCAST
@@ -451,25 +462,25 @@ static int gre_rcv(struct sk_buff *skb)
 	}
 #endif
 
-	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
+	hdr_len = gre_parse_header(skb, &tpi, &reason, htons(ETH_P_IP), 0);
 	if (hdr_len < 0)
 		goto drop;
 
 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
 		     tpi.proto == htons(ETH_P_ERSPAN2))) {
-		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
+		if (erspan_rcv(skb, &tpi, hdr_len, &reason) == PACKET_RCVD)
 			return 0;
 		goto out;
 	}
 
-	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
+	if (ipgre_rcv(skb, &tpi, hdr_len, &reason) == PACKET_RCVD)
 		return 0;
 
 out:
 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 drop:
 	dev_core_stats_rx_dropped_inc(skb->dev);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return 0;
 }
 
@@ -496,6 +507,7 @@ static int gre_handle_offloads(struct sk_buff *skb, bool csum)
 static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 			__be16 proto)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	IP_TUNNEL_DECLARE_FLAGS(flags) = { };
 	struct ip_tunnel_info *tun_info;
@@ -504,19 +516,25 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 
 	tun_info = skb_tunnel_info(skb);
 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
-		     ip_tunnel_info_af(tun_info) != AF_INET))
+		     ip_tunnel_info_af(tun_info) != AF_INET)) {
+		reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 		goto err_free_skb;
+	}
 
 	key = &tun_info->key;
 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
 
-	if (skb_cow_head(skb, dev->needed_headroom))
+	if (skb_cow_head(skb, dev->needed_headroom)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto err_free_skb;
+	}
 
 	/* Push Tunnel header. */
 	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
-					      tunnel->parms.o_flags)))
+					      tunnel->parms.o_flags))) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto err_free_skb;
+	}
 
 	__set_bit(IP_TUNNEL_CSUM_BIT, flags);
 	__set_bit(IP_TUNNEL_KEY_BIT, flags);
@@ -533,12 +551,13 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 	return;
 
 err_free_skb:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	DEV_STATS_INC(dev, tx_dropped);
 }
 
 static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	IP_TUNNEL_DECLARE_FLAGS(flags) = { };
 	struct ip_tunnel_info *tun_info;
@@ -552,29 +571,41 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	tun_info = skb_tunnel_info(skb);
 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
-		     ip_tunnel_info_af(tun_info) != AF_INET))
+		     ip_tunnel_info_af(tun_info) != AF_INET)) {
+		reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 		goto err_free_skb;
+	}
 
 	key = &tun_info->key;
-	if (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT, tun_info->key.tun_flags))
+	if (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT, tun_info->key.tun_flags)) {
+		reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 		goto err_free_skb;
-	if (tun_info->options_len < sizeof(*md))
+	}
+	if (tun_info->options_len < sizeof(*md)) {
+		reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 		goto err_free_skb;
+	}
 	md = ip_tunnel_info_opts(tun_info);
 
 	/* ERSPAN has fixed 8 byte GRE header */
 	version = md->version;
 	tunnel_hlen = 8 + erspan_hdr_len(version);
 
-	if (skb_cow_head(skb, dev->needed_headroom))
+	if (skb_cow_head(skb, dev->needed_headroom)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto err_free_skb;
+	}
 
-	if (gre_handle_offloads(skb, false))
+	if (gre_handle_offloads(skb, false)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto err_free_skb;
+	}
 
 	if (skb->len > dev->mtu + dev->hard_header_len) {
-		if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+		if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) {
+			reason = SKB_DROP_REASON_NOMEM;
 			goto err_free_skb;
+		}
 		truncate = true;
 	}
 
@@ -606,6 +637,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 				       truncate, true);
 		proto = htons(ETH_P_ERSPAN2);
 	} else {
+		reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 		goto err_free_skb;
 	}
 
@@ -618,7 +650,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 	return;
 
 err_free_skb:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	DEV_STATS_INC(dev, tx_dropped);
 }
 
@@ -649,11 +681,13 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
 			      struct net_device *dev)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	IP_TUNNEL_DECLARE_FLAGS(flags);
 	const struct iphdr *tnl_params;
 
-	if (!pskb_inet_may_pull(skb))
+	reason = pskb_inet_may_pull_reason(skb);
+	if (reason)
 		goto free_skb;
 
 	if (tunnel->collect_md) {
@@ -664,10 +698,13 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
 	if (dev->header_ops) {
 		int pull_len = tunnel->hlen + sizeof(struct iphdr);
 
-		if (skb_cow_head(skb, 0))
+		if (skb_cow_head(skb, 0)) {
+			reason = SKB_DROP_REASON_NOMEM;
 			goto free_skb;
+		}
 
-		if (!pskb_may_pull(skb, pull_len))
+		reason = pskb_may_pull_reason(skb, pull_len);
+		if (reason)
 			goto free_skb;
 
 		tnl_params = (const struct iphdr *)skb->data;
@@ -677,25 +714,31 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
 		skb_reset_mac_header(skb);
 
 		if (skb->ip_summed == CHECKSUM_PARTIAL &&
-		    skb_checksum_start(skb) < skb->data)
+		    skb_checksum_start(skb) < skb->data) {
+			reason = SKB_DROP_REASON_SKB_CSUM;
 			goto free_skb;
+		}
 	} else {
-		if (skb_cow_head(skb, dev->needed_headroom))
+		if (skb_cow_head(skb, dev->needed_headroom)) {
+			reason = SKB_DROP_REASON_NOMEM;
 			goto free_skb;
+		}
 
 		tnl_params = &tunnel->parms.iph;
 	}
 
 	ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
 
-	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags)))
+	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags))) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto free_skb;
+	}
 
 	__gre_xmit(skb, dev, tnl_params, skb->protocol, flags);
 	return NETDEV_TX_OK;
 
 free_skb:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	DEV_STATS_INC(dev, tx_dropped);
 	return NETDEV_TX_OK;
 }
@@ -703,12 +746,14 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
 static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 			       struct net_device *dev)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	IP_TUNNEL_DECLARE_FLAGS(flags);
 	bool truncate = false;
 	__be16 proto;
 
-	if (!pskb_inet_may_pull(skb))
+	reason = pskb_inet_may_pull_reason(skb);
+	if (reason)
 		goto free_skb;
 
 	if (tunnel->collect_md) {
@@ -716,15 +761,21 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
-	if (gre_handle_offloads(skb, false))
+	if (gre_handle_offloads(skb, false)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto free_skb;
+	}
 
-	if (skb_cow_head(skb, dev->needed_headroom))
+	if (skb_cow_head(skb, dev->needed_headroom)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto free_skb;
+	}
 
 	if (skb->len > dev->mtu + dev->hard_header_len) {
-		if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+		if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) {
+			reason = SKB_DROP_REASON_NOMEM;
 			goto free_skb;
+		}
 		truncate = true;
 	}
 
@@ -745,6 +796,7 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 				       truncate, true);
 		proto = htons(ETH_P_ERSPAN2);
 	} else {
+		reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 		goto free_skb;
 	}
 
@@ -753,7 +805,7 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 	return NETDEV_TX_OK;
 
 free_skb:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	DEV_STATS_INC(dev, tx_dropped);
 	return NETDEV_TX_OK;
 }
@@ -761,10 +813,12 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
 				struct net_device *dev)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	IP_TUNNEL_DECLARE_FLAGS(flags);
 
-	if (!pskb_inet_may_pull(skb))
+	reason = pskb_inet_may_pull_reason(skb);
+	if (reason)
 		goto free_skb;
 
 	if (tunnel->collect_md) {
@@ -774,17 +828,21 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
 
 	ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
 
-	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags)))
+	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags))) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto free_skb;
+	}
 
-	if (skb_cow_head(skb, dev->needed_headroom))
+	if (skb_cow_head(skb, dev->needed_headroom)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto free_skb;
+	}
 
 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB), flags);
 	return NETDEV_TX_OK;
 
 free_skb:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	DEV_STATS_INC(dev, tx_dropped);
 	return NETDEV_TX_OK;
 }
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 13b5e35e8790b..e7757c0a09be4 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -378,6 +378,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
 		  const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,
 		  bool log_ecn_error)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	const struct iphdr *iph = ip_hdr(skb);
 	int nh, err;
 
@@ -392,14 +393,22 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
 	    test_bit(IP_TUNNEL_CSUM_BIT, tpi->flags)) {
 		DEV_STATS_INC(tunnel->dev, rx_crc_errors);
 		DEV_STATS_INC(tunnel->dev, rx_errors);
+		reason = SKB_DROP_REASON_TNL_OPT_MISMATCH;
 		goto drop;
 	}
 
 	if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.i_flags)) {
-		if (!test_bit(IP_TUNNEL_SEQ_BIT, tpi->flags) ||
-		    (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
+		if (!test_bit(IP_TUNNEL_SEQ_BIT, tpi->flags)) {
 			DEV_STATS_INC(tunnel->dev, rx_fifo_errors);
 			DEV_STATS_INC(tunnel->dev, rx_errors);
+			reason = SKB_DROP_REASON_TNL_OPT_MISMATCH;
+			goto drop;
+		}
+		if (tunnel->i_seqno &&
+		    (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0) {
+			DEV_STATS_INC(tunnel->dev, rx_fifo_errors);
+			DEV_STATS_INC(tunnel->dev, rx_errors);
+			reason = SKB_DROP_REASON_TNL_OLD_SEQ;
 			goto drop;
 		}
 		tunnel->i_seqno = ntohl(tpi->seq) + 1;
@@ -413,7 +422,8 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
 
 	skb_set_network_header(skb, (tunnel->dev->type == ARPHRD_ETHER) ? ETH_HLEN : 0);
 
-	if (!pskb_inet_may_pull(skb)) {
+	reason = pskb_inet_may_pull_reason(skb);
+	if (reason) {
 		DEV_STATS_INC(tunnel->dev, rx_length_errors);
 		DEV_STATS_INC(tunnel->dev, rx_errors);
 		goto drop;
@@ -428,6 +438,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
 		if (err > 1) {
 			DEV_STATS_INC(tunnel->dev, rx_frame_errors);
 			DEV_STATS_INC(tunnel->dev, rx_errors);
+			reason = SKB_DROP_REASON_IP_TUNNEL_ECN;
 			goto drop;
 		}
 	}
@@ -451,7 +462,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
 drop:
 	if (tun_dst)
 		dst_release((struct dst_entry *)tun_dst);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
@@ -569,6 +580,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
 void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 		       u8 proto, int tunnel_hlen)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	u32 headroom = sizeof(struct iphdr);
 	struct ip_tunnel_info *tun_info;
@@ -582,8 +594,10 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
 	tun_info = skb_tunnel_info(skb);
 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
-		     ip_tunnel_info_af(tun_info) != AF_INET))
+		     ip_tunnel_info_af(tun_info) != AF_INET)) {
+		reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 		goto tx_error;
+	}
 	key = &tun_info->key;
 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
 	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
@@ -602,8 +616,10 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	if (!tunnel_hlen)
 		tunnel_hlen = ip_encap_hlen(&tun_info->encap);
 
-	if (ip_tunnel_encap(skb, &tun_info->encap, &proto, &fl4) < 0)
+	if (ip_tunnel_encap(skb, &tun_info->encap, &proto, &fl4) < 0) {
+		reason = SKB_DROP_REASON_TNL_ENCAP;
 		goto tx_error;
+	}
 
 	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
 	if (use_cache)
@@ -612,6 +628,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 		rt = ip_route_output_key(tunnel->net, &fl4);
 		if (IS_ERR(rt)) {
 			DEV_STATS_INC(dev, tx_carrier_errors);
+			reason = SKB_DROP_REASON_IP_OUTNOROUTES;
 			goto tx_error;
 		}
 		if (use_cache)
@@ -621,6 +638,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	if (rt->dst.dev == dev) {
 		ip_rt_put(rt);
 		DEV_STATS_INC(dev, collisions);
+		reason = SKB_DROP_REASON_RECURSION_LIMIT;
 		goto tx_error;
 	}
 
@@ -629,6 +647,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, tunnel_hlen,
 			    key->u.ipv4.dst, true)) {
 		ip_rt_put(rt);
+		reason = SKB_DROP_REASON_PKT_TOO_BIG;
 		goto tx_error;
 	}
 
@@ -646,6 +665,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
 	if (skb_cow_head(skb, headroom)) {
 		ip_rt_put(rt);
+		reason = SKB_DROP_REASON_NOMEM;
 		goto tx_dropped;
 	}
 
@@ -660,13 +680,14 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 tx_dropped:
 	DEV_STATS_INC(dev, tx_dropped);
 kfree:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 }
 EXPORT_SYMBOL_GPL(ip_md_tunnel_xmit);
 
 void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 		    const struct iphdr *tnl_params, u8 protocol)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	struct ip_tunnel_info *tun_info = NULL;
 	const struct iphdr *inner_iph;
@@ -694,9 +715,15 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
 		if (!skb_dst(skb)) {
 			DEV_STATS_INC(dev, tx_fifo_errors);
+			reason = SKB_DROP_REASON_NO_TX_TARGET;
 			goto tx_error;
 		}
 
+		/* Only the branches below can derive a destination.  If
+		 * none of them matches, the payload protocol is not one
+		 * this tunnel can carry.
+		 */
+		reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 		tun_info = skb_tunnel_info(skb);
 		if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
 		    ip_tunnel_info_af(tun_info) == AF_INET &&
@@ -717,8 +744,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
 			neigh = dst_neigh_lookup(skb_dst(skb),
 						 &ipv6_hdr(skb)->daddr);
-			if (!neigh)
+			if (!neigh) {
+				reason = SKB_DROP_REASON_NEIGH_CREATEFAIL;
 				goto tx_error;
+			}
 
 			addr6 = (const struct in6_addr *)&neigh->primary_key;
 			addr_type = ipv6_addr_type(addr6);
@@ -735,8 +764,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 				dst = addr6->s6_addr32[3];
 			}
 			neigh_release(neigh);
-			if (do_tx_error_icmp)
+			if (do_tx_error_icmp) {
+				reason = SKB_DROP_REASON_NO_TX_TARGET;
 				goto tx_error_icmp;
+			}
 		}
 #endif
 		else
@@ -763,8 +794,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 			    tunnel->net, READ_ONCE(tunnel->parms.link),
 			    tunnel->fwmark, skb_get_hash(skb), 0);
 
-	if (ip_tunnel_encap(skb, &tunnel->encap, &protocol, &fl4) < 0)
+	if (ip_tunnel_encap(skb, &tunnel->encap, &protocol, &fl4) < 0) {
+		reason = SKB_DROP_REASON_TNL_ENCAP;
 		goto tx_error;
+	}
 
 	if (connected && md) {
 		use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
@@ -781,6 +814,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
 		if (IS_ERR(rt)) {
 			DEV_STATS_INC(dev, tx_carrier_errors);
+			reason = SKB_DROP_REASON_IP_OUTNOROUTES;
 			goto tx_error;
 		}
 		if (use_cache)
@@ -794,6 +828,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	if (rt->dst.dev == dev) {
 		ip_rt_put(rt);
 		DEV_STATS_INC(dev, collisions);
+		reason = SKB_DROP_REASON_RECURSION_LIMIT;
 		goto tx_error;
 	}
 
@@ -803,6 +838,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
 	if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) {
 		ip_rt_put(rt);
+		reason = SKB_DROP_REASON_PKT_TOO_BIG;
 		goto tx_error;
 	}
 
@@ -837,7 +873,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	if (skb_cow_head(skb, max_headroom)) {
 		ip_rt_put(rt);
 		DEV_STATS_INC(dev, tx_dropped);
-		kfree_skb(skb);
+		kfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);
 		return;
 	}
 
@@ -853,7 +889,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 #endif
 tx_error:
 	DEV_STATS_INC(dev, tx_errors);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_xmit);
 
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 8ebda0b6a78b2..a510be5ad702f 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -454,7 +454,8 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	return 0;
 }
 
-static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
+static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
+		      enum skb_drop_reason *reason)
 {
 	const struct ipv6hdr *ipv6h;
 	struct ip6_tnl *tunnel;
@@ -473,8 +474,10 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
 			tun_id = key32_to_tunnel_id(tpi->key);
 
 			tun_dst = ipv6_tun_rx_dst(skb, flags, tun_id, 0);
-			if (!tun_dst)
+			if (!tun_dst) {
+				*reason = SKB_DROP_REASON_NOMEM;
 				return PACKET_REJECT;
+			}
 
 			ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
 		} else {
@@ -484,12 +487,14 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
 		return PACKET_RCVD;
 	}
 
+	*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;
 	return PACKET_REJECT;
 }
 
 static int ip6erspan_rcv(struct sk_buff *skb,
 			 struct tnl_ptk_info *tpi,
-			 int gre_hdr_len)
+			 int gre_hdr_len,
+			 enum skb_drop_reason *reason)
 {
 	struct erspan_base_hdr *ershdr;
 	const struct ipv6hdr *ipv6h;
@@ -497,8 +502,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,
 	struct ip6_tnl *tunnel;
 	u8 ver;
 
-	if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
+	if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) {
+		*reason = SKB_DROP_REASON_HDR_TRUNC;
 		return PACKET_REJECT;
+	}
 
 	ipv6h = ipv6_hdr(skb);
 	ershdr = (struct erspan_base_hdr *)skb->data;
@@ -510,13 +517,17 @@ static int ip6erspan_rcv(struct sk_buff *skb,
 	if (tunnel) {
 		int len = erspan_hdr_len(ver);
 
-		if (unlikely(!pskb_may_pull(skb, len)))
+		if (unlikely(!pskb_may_pull(skb, len))) {
+			*reason = SKB_DROP_REASON_HDR_TRUNC;
 			return PACKET_REJECT;
+		}
 
 		if (__iptunnel_pull_header(skb, len,
 					   htons(ETH_P_TEB),
-					   false, false) < 0)
+					   false, false) < 0) {
+			*reason = SKB_DROP_REASON_HDR_TRUNC;
 			return PACKET_REJECT;
+		}
 
 		if (tunnel->parms.collect_md) {
 			struct erspan_metadata *pkt_md, *md;
@@ -532,8 +543,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,
 
 			tun_dst = ipv6_tun_rx_dst(skb, flags, tun_id,
 						  sizeof(*md));
-			if (!tun_dst)
+			if (!tun_dst) {
+				*reason = SKB_DROP_REASON_NOMEM;
 				return PACKET_REJECT;
+			}
 
 			/* MUST set options_len before referencing options */
 			info = &tun_dst->u.tun_info;
@@ -564,37 +577,40 @@ static int ip6erspan_rcv(struct sk_buff *skb,
 		return PACKET_RCVD;
 	}
 
+	*reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;
 	return PACKET_REJECT;
 }
 
 static int gre_rcv(struct sk_buff *skb)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct tnl_ptk_info tpi;
-	bool csum_err = false;
 	int hdr_len;
 
-	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IPV6), 0);
+	hdr_len = gre_parse_header(skb, &tpi, &reason, htons(ETH_P_IPV6), 0);
 	if (hdr_len < 0)
 		goto drop;
 
-	if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))
+	if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) {
+		reason = SKB_DROP_REASON_HDR_TRUNC;
 		goto drop;
+	}
 
 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
 		     tpi.proto == htons(ETH_P_ERSPAN2))) {
-		if (ip6erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
+		if (ip6erspan_rcv(skb, &tpi, hdr_len, &reason) == PACKET_RCVD)
 			return 0;
 		goto out;
 	}
 
-	if (ip6gre_rcv(skb, &tpi) == PACKET_RCVD)
+	if (ip6gre_rcv(skb, &tpi, &reason) == PACKET_RCVD)
 		return 0;
 
 out:
 	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
 drop:
 	dev_core_stats_rx_dropped_inc(skb->dev);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return 0;
 }
 
@@ -718,7 +734,8 @@ static struct ip_tunnel_info *skb_tunnel_info_txcheck(struct sk_buff *skb)
 static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
 			       struct net_device *dev, __u8 dsfield,
 			       struct flowi6 *fl6, int encap_limit,
-			       __u32 *pmtu, __be16 proto)
+			       __u32 *pmtu, __be16 proto,
+			       enum skb_drop_reason *reason)
 {
 	struct ip6_tnl *tunnel = netdev_priv(dev);
 	IP_TUNNEL_DECLARE_FLAGS(flags);
@@ -742,8 +759,10 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
 
 		tun_info = skb_tunnel_info_txcheck(skb);
 		if (IS_ERR(tun_info) ||
-		    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6))
+		    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6)) {
+			*reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 			return -EINVAL;
+		}
 
 		key = &tun_info->key;
 		memset(fl6, 0, sizeof(*fl6));
@@ -761,8 +780,11 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
 		ip_tunnel_flags_and(flags, flags, key->tun_flags);
 		tun_hlen = gre_calc_hlen(flags);
 
-		if (skb_cow_head(skb, dev->needed_headroom ?: tun_hlen + tunnel->encap_hlen))
+		if (skb_cow_head(skb, dev->needed_headroom ?:
+				 tun_hlen + tunnel->encap_hlen)) {
+			*reason = SKB_DROP_REASON_NOMEM;
 			return -ENOMEM;
+		}
 
 		gre_build_header(skb, tun_hlen,
 				 flags, protocol,
@@ -772,8 +794,10 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
 				 0);
 
 	} else {
-		if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen))
+		if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen)) {
+			*reason = SKB_DROP_REASON_NOMEM;
 			return -ENOMEM;
+		}
 
 		ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
 
@@ -785,10 +809,11 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
 	}
 
 	return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu,
-			    NEXTHDR_GRE);
+			    NEXTHDR_GRE, reason);
 }
 
-static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
+static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev,
+				   enum skb_drop_reason *reason)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	int encap_limit = -1;
@@ -805,11 +830,13 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
 
 	err = gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
 						t->parms.o_flags));
-	if (err)
+	if (err) {
+		*reason = SKB_DROP_REASON_NOMEM;
 		return -1;
+	}
 
 	err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
-			  skb->protocol);
+			  skb->protocol, reason);
 	if (err != 0) {
 		/* XXX: send ICMP error even if DF is not set. */
 		if (err == -EMSGSIZE)
@@ -821,7 +848,8 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 }
 
-static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
+static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev,
+				   enum skb_drop_reason *reason)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
@@ -831,19 +859,25 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
 	__u32 mtu;
 	int err;
 
-	if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr))
+	if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr)) {
+		*reason = SKB_DROP_REASON_RECURSION_LIMIT;
 		return -1;
+	}
 
 	if (!t->parms.collect_md &&
-	    prepare_ip6gre_xmit_ipv6(skb, dev, &fl6, &dsfield, &encap_limit))
+	    prepare_ip6gre_xmit_ipv6(skb, dev, &fl6, &dsfield, &encap_limit)) {
+		*reason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;
 		return -1;
+	}
 
 	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
-					      t->parms.o_flags)))
+					      t->parms.o_flags))) {
+		*reason = SKB_DROP_REASON_NOMEM;
 		return -1;
+	}
 
 	err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit,
-			  &mtu, skb->protocol);
+			  &mtu, skb->protocol, reason);
 	if (err != 0) {
 		if (err == -EMSGSIZE)
 			icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
@@ -853,7 +887,8 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 }
 
-static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev)
+static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev,
+			     enum skb_drop_reason *reason)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	int encap_limit = -1;
@@ -863,14 +898,19 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev)
 	int err;
 
 	if (!t->parms.collect_md &&
-	    prepare_ip6gre_xmit_other(skb, dev, &fl6, &dsfield, &encap_limit))
+	    prepare_ip6gre_xmit_other(skb, dev, &fl6, &dsfield, &encap_limit)) {
+		*reason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;
 		return -1;
+	}
 
 	err = gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
 						t->parms.o_flags));
-	if (err)
+	if (err) {
+		*reason = SKB_DROP_REASON_NOMEM;
 		return err;
-	err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, skb->protocol);
+	}
+	err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
+			  skb->protocol, reason);
 
 	return err;
 }
@@ -878,16 +918,20 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev)
 static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
 	struct net_device *dev)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel_info *tun_info = NULL;
 	struct ip6_tnl *t = netdev_priv(dev);
 	__be16 payload_protocol;
 	int ret;
 
-	if (!pskb_inet_may_pull(skb))
+	reason = pskb_inet_may_pull_reason(skb);
+	if (reason)
 		goto tx_err;
 
-	if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr))
+	if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr)) {
+		reason = SKB_DROP_REASON_DEV_READY;
 		goto tx_err;
+	}
 
 	if (t->parms.collect_md)
 		tun_info = skb_tunnel_info_txcheck(skb);
@@ -895,13 +939,13 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
 	payload_protocol = skb_protocol(skb, true);
 	switch (payload_protocol) {
 	case htons(ETH_P_IP):
-		ret = ip6gre_xmit_ipv4(skb, dev);
+		ret = ip6gre_xmit_ipv4(skb, dev, &reason);
 		break;
 	case htons(ETH_P_IPV6):
-		ret = ip6gre_xmit_ipv6(skb, dev);
+		ret = ip6gre_xmit_ipv6(skb, dev, &reason);
 		break;
 	default:
-		ret = ip6gre_xmit_other(skb, dev);
+		ret = ip6gre_xmit_other(skb, dev, &reason);
 		break;
 	}
 
@@ -914,13 +958,14 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
 	if (!IS_ERR(tun_info))
 		DEV_STATS_INC(dev, tx_errors);
 	DEV_STATS_INC(dev, tx_dropped);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return NETDEV_TX_OK;
 }
 
 static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 					 struct net_device *dev)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip_tunnel_info *tun_info = NULL;
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct dst_entry *dst = skb_dst(skb);
@@ -934,18 +979,25 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 	__u32 mtu;
 	int nhoff;
 
-	if (!pskb_inet_may_pull(skb))
+	reason = pskb_inet_may_pull_reason(skb);
+	if (reason)
 		goto tx_err;
 
-	if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr))
+	if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr)) {
+		reason = SKB_DROP_REASON_DEV_READY;
 		goto tx_err;
+	}
 
-	if (gre_handle_offloads(skb, false))
+	if (gre_handle_offloads(skb, false)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto tx_err;
+	}
 
 	if (skb->len > dev->mtu + dev->hard_header_len) {
-		if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+		if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) {
+			reason = SKB_DROP_REASON_NOMEM;
 			goto tx_err;
+		}
 		truncate = true;
 	}
 
@@ -965,8 +1017,10 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 			truncate = true;
 	}
 
-	if (skb_cow_head(skb, dev->needed_headroom ?: t->hlen))
+	if (skb_cow_head(skb, dev->needed_headroom ?: t->hlen)) {
+		reason = SKB_DROP_REASON_NOMEM;
 		goto tx_err;
+	}
 
 	IPCB(skb)->flags = 0;
 
@@ -980,8 +1034,10 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 
 		tun_info = skb_tunnel_info_txcheck(skb);
 		if (IS_ERR(tun_info) ||
-		    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6))
+		    unlikely(ip_tunnel_info_af(tun_info) != AF_INET6)) {
+			reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 			goto tx_err;
+		}
 
 		key = &tun_info->key;
 		memset(&fl6, 0, sizeof(fl6));
@@ -993,10 +1049,14 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 
 		dsfield = key->tos;
 		if (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT,
-			      tun_info->key.tun_flags))
+			      tun_info->key.tun_flags)) {
+			reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 			goto tx_err;
-		if (tun_info->options_len < sizeof(*md))
+		}
+		if (tun_info->options_len < sizeof(*md)) {
+			reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 			goto tx_err;
+		}
 		md = ip_tunnel_info_opts(tun_info);
 
 		tun_id = tunnel_id_to_key32(key->tun_id);
@@ -1014,6 +1074,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 					       truncate, false);
 			proto = htons(ETH_P_ERSPAN2);
 		} else {
+			reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 			goto tx_err;
 		}
 	} else {
@@ -1024,11 +1085,16 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 						 &dsfield, &encap_limit);
 			break;
 		case htons(ETH_P_IPV6):
-			if (ipv6_addr_equal(&t->parms.raddr, &ipv6_hdr(skb)->saddr))
+			if (ipv6_addr_equal(&t->parms.raddr,
+					    &ipv6_hdr(skb)->saddr)) {
+				reason = SKB_DROP_REASON_RECURSION_LIMIT;
 				goto tx_err;
+			}
 			if (prepare_ip6gre_xmit_ipv6(skb, dev, &fl6,
-						     &dsfield, &encap_limit))
+						     &dsfield, &encap_limit)) {
+				reason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;
 				goto tx_err;
+			}
 			break;
 		default:
 			memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
@@ -1047,6 +1113,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 					       truncate, false);
 			proto = htons(ETH_P_ERSPAN2);
 		} else {
+			reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 			goto tx_err;
 		}
 
@@ -1065,7 +1132,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 			dst->ops->update_pmtu(dst, NULL, skb, mtu, false);
 	}
 	err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
-			   NEXTHDR_GRE);
+			   NEXTHDR_GRE, &reason);
 	if (err != 0) {
 		/* XXX: send ICMP error even if DF is not set. */
 		if (err == -EMSGSIZE) {
@@ -1084,7 +1151,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 	if (!IS_ERR(tun_info))
 		DEV_STATS_INC(dev, tx_errors);
 	DEV_STATS_INC(dev, tx_dropped);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return NETDEV_TX_OK;
 }
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index d5ff50a2ac017..d804c67c4be3b 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -813,6 +813,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
 						struct sk_buff *skb),
 			 bool log_ecn_err)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	const struct ipv6hdr *ipv6h;
 	int nh, err;
 
@@ -820,15 +821,22 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
 	    test_bit(IP_TUNNEL_CSUM_BIT, tpi->flags)) {
 		DEV_STATS_INC(tunnel->dev, rx_crc_errors);
 		DEV_STATS_INC(tunnel->dev, rx_errors);
+		reason = SKB_DROP_REASON_TNL_OPT_MISMATCH;
 		goto drop;
 	}
 
 	if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.i_flags)) {
-		if (!test_bit(IP_TUNNEL_SEQ_BIT, tpi->flags) ||
-		    (tunnel->i_seqno &&
-		     (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
+		if (!test_bit(IP_TUNNEL_SEQ_BIT, tpi->flags)) {
 			DEV_STATS_INC(tunnel->dev, rx_fifo_errors);
 			DEV_STATS_INC(tunnel->dev, rx_errors);
+			reason = SKB_DROP_REASON_TNL_OPT_MISMATCH;
+			goto drop;
+		}
+		if (tunnel->i_seqno &&
+		    (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0) {
+			DEV_STATS_INC(tunnel->dev, rx_fifo_errors);
+			DEV_STATS_INC(tunnel->dev, rx_errors);
+			reason = SKB_DROP_REASON_TNL_OLD_SEQ;
 			goto drop;
 		}
 		tunnel->i_seqno = ntohl(tpi->seq) + 1;
@@ -838,7 +846,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
 
 	/* Warning: All skb pointers will be invalidated! */
 	if (tunnel->dev->type == ARPHRD_ETHER) {
-		if (!pskb_may_pull(skb, ETH_HLEN)) {
+		reason = pskb_may_pull_reason(skb, ETH_HLEN);
+		if (reason) {
 			DEV_STATS_INC(tunnel->dev, rx_length_errors);
 			DEV_STATS_INC(tunnel->dev, rx_errors);
 			goto drop;
@@ -859,7 +868,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
 
 	skb_reset_network_header(skb);
 
-	if (skb_vlan_inet_prepare(skb, true)) {
+	reason = skb_vlan_inet_prepare(skb, true);
+	if (reason) {
 		DEV_STATS_INC(tunnel->dev, rx_length_errors);
 		DEV_STATS_INC(tunnel->dev, rx_errors);
 		goto drop;
@@ -881,6 +891,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
 		if (err > 1) {
 			DEV_STATS_INC(tunnel->dev, rx_frame_errors);
 			DEV_STATS_INC(tunnel->dev, rx_errors);
+			reason = SKB_DROP_REASON_IP_TUNNEL_ECN;
 			goto drop;
 		}
 	}
@@ -898,7 +909,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
 drop:
 	if (tun_dst)
 		dst_release((struct dst_entry *)tun_dst);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return 0;
 }
 
@@ -1086,6 +1097,7 @@ EXPORT_SYMBOL_GPL(ip6_tnl_xmit_ctl);
  *   @encap_limit: encapsulation limit
  *   @pmtu: Path MTU is stored if packet is too big
  *   @proto: next header value
+ *   @reason: drop reason, only written when the packet is dropped
  *
  * Description:
  *   Build new header and do some sanity checks on the packet before sending
@@ -1099,7 +1111,7 @@ EXPORT_SYMBOL_GPL(ip6_tnl_xmit_ctl);
 
 int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 		 struct flowi6 *fl6, int encap_limit, __u32 *pmtu,
-		 __u8 proto)
+		 __u8 proto, enum skb_drop_reason *reason)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net *net = t->net;
@@ -1132,13 +1144,17 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 			struct neighbour *neigh;
 			int addr_type;
 
-			if (!skb_dst(skb))
+			if (!skb_dst(skb)) {
+				*reason = SKB_DROP_REASON_NO_TX_TARGET;
 				goto tx_err_link_failure;
+			}
 
 			neigh = dst_neigh_lookup(skb_dst(skb),
 						 &ipv6_hdr(skb)->daddr);
-			if (!neigh)
+			if (!neigh) {
+				*reason = SKB_DROP_REASON_NEIGH_CREATEFAIL;
 				goto tx_err_link_failure;
+			}
 
 			addr6 = (struct in6_addr *)&neigh->primary_key;
 			addr_type = ipv6_addr_type(addr6);
@@ -1151,8 +1167,10 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 		} else if (payload_protocol == htons(ETH_P_IP)) {
 			const struct rtable *rt = skb_rtable(skb);
 
-			if (!rt)
+			if (!rt) {
+				*reason = SKB_DROP_REASON_IP_OUTNOROUTES;
 				goto tx_err_link_failure;
+			}
 
 			if (rt->rt_gw_family == AF_INET6)
 				memcpy(&fl6->daddr, &rt->rt_gw6, sizeof(fl6->daddr));
@@ -1169,8 +1187,10 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 	if (use_cache)
 		dst = dst_cache_get(&t->dst_cache);
 
-	if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
+	if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr)) {
+		*reason = SKB_DROP_REASON_DEV_READY;
 		goto tx_err_link_failure;
+	}
 
 	if (!dst) {
 route_lookup:
@@ -1179,18 +1199,23 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 
 		dst = ip6_route_output(net, NULL, fl6);
 
-		if (dst->error)
+		if (dst->error) {
+			*reason = SKB_DROP_REASON_IP_OUTNOROUTES;
 			goto tx_err_link_failure;
+		}
 		dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0);
 		if (IS_ERR(dst)) {
 			err = PTR_ERR(dst);
 			dst = NULL;
+			*reason = SKB_DROP_REASON_IP_OUTNOROUTES;
 			goto tx_err_link_failure;
 		}
 		if (t->parms.collect_md && ipv6_addr_any(&fl6->saddr) &&
 		    ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev,
-				       &fl6->daddr, 0, &fl6->saddr))
+				       &fl6->daddr, 0, &fl6->saddr)) {
+			*reason = SKB_DROP_REASON_NO_TX_TARGET;
 			goto tx_err_link_failure;
+		}
 		ndst = dst;
 	}
 
@@ -1200,6 +1225,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 		DEV_STATS_INC(dev, collisions);
 		net_warn_ratelimited("%s: Local routing loop detected!\n",
 				     t->parms.name);
+		*reason = SKB_DROP_REASON_RECURSION_LIMIT;
 		goto tx_err_dst_release;
 	}
 	mtu = dst6_mtu(dst) - eth_hlen - psh_hlen - t->tun_hlen;
@@ -1214,6 +1240,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 	if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) {
 		*pmtu = mtu;
 		err = -EMSGSIZE;
+		*reason = SKB_DROP_REASON_PKT_TOO_BIG;
 		goto tx_err_dst_release;
 	}
 
@@ -1236,12 +1263,16 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 	 */
 	max_headroom += LL_RESERVED_SPACE(tdev);
 
-	if (skb_cow_head(skb, max_headroom))
+	if (skb_cow_head(skb, max_headroom)) {
+		*reason = SKB_DROP_REASON_NOMEM;
 		goto tx_err_dst_release;
+	}
 
 	if (t->parms.collect_md) {
-		if (t->encap.type != TUNNEL_ENCAP_NONE)
+		if (t->encap.type != TUNNEL_ENCAP_NONE) {
+			*reason = SKB_DROP_REASON_TNL_ENCAP;
 			goto tx_err_dst_release;
+		}
 	} else {
 		if (use_cache && ndst)
 			dst_cache_set_ip6(&t->dst_cache, ndst, &fl6->saddr);
@@ -1265,8 +1296,10 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 	ip_tunnel_adj_headroom(dev, max_headroom);
 
 	err = ip6_tnl_encap(skb, t, &proto, fl6);
-	if (err)
+	if (err) {
+		*reason = SKB_DROP_REASON_TNL_ENCAP;
 		return err;
+	}
 
 	if (encap_limit >= 0) {
 		init_tel_txopt(&opt, encap_limit);
@@ -1295,7 +1328,7 @@ EXPORT_SYMBOL(ip6_tnl_xmit);
 
 static inline int
 ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
-		u8 protocol)
+		u8 protocol, enum skb_drop_reason *reason)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct ipv6hdr *ipv6h;
@@ -1309,8 +1342,10 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
 	int err;
 
 	tproto = READ_ONCE(t->parms.proto);
-	if (tproto != protocol && tproto != 0)
+	if (tproto != protocol && tproto != 0) {
+		*reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 		return -1;
+	}
 
 	if (t->parms.collect_md) {
 		struct ip_tunnel_info *tun_info;
@@ -1318,8 +1353,10 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
 
 		tun_info = skb_tunnel_info(skb);
 		if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
-			     ip_tunnel_info_af(tun_info) != AF_INET6))
+			     ip_tunnel_info_af(tun_info) != AF_INET6)) {
+			*reason = SKB_DROP_REASON_TUNNEL_TXINFO;
 			return -1;
+		}
 		key = &tun_info->key;
 		memset(&fl6, 0, sizeof(fl6));
 		fl6.flowi6_proto = protocol;
@@ -1356,6 +1393,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
 				if (tel->encap_limit == 0) {
 					icmpv6_ndo_send(skb, ICMPV6_PARAMPROB,
 							ICMPV6_HDR_FIELD, offset + 2);
+					*reason = SKB_DROP_REASON_IPV6_BAD_EXTHDR;
 					return -1;
 				}
 				encap_limit = tel->encap_limit - 1;
@@ -1397,13 +1435,15 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
 	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
 	dsfield = INET_ECN_encapsulate(dsfield, orig_dsfield);
 
-	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
+	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) {
+		*reason = SKB_DROP_REASON_NOMEM;
 		return -1;
+	}
 
 	skb_set_inner_ipproto(skb, protocol);
 
 	err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
-			   protocol);
+			   protocol, reason);
 	if (err != 0) {
 		/* XXX: send ICMP error even if DF is not set. */
 		if (err == -EMSGSIZE)
@@ -1418,6 +1458,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
 			default:
 				break;
 			}
+		*reason = SKB_DROP_REASON_PKT_TOO_BIG;
 		return -1;
 	}
 
@@ -1427,11 +1468,13 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
 static netdev_tx_t
 ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	struct ip6_tnl *t = netdev_priv(dev);
 	u8 ipproto;
 	int ret;
 
-	if (!pskb_inet_may_pull(skb))
+	reason = pskb_inet_may_pull_reason(skb);
+	if (reason)
 		goto tx_err;
 
 	switch (skb->protocol) {
@@ -1439,18 +1482,21 @@ ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		ipproto = IPPROTO_IPIP;
 		break;
 	case htons(ETH_P_IPV6):
-		if (ip6_tnl_addr_conflict(t, ipv6_hdr(skb)))
+		if (ip6_tnl_addr_conflict(t, ipv6_hdr(skb))) {
+			reason = SKB_DROP_REASON_RECURSION_LIMIT;
 			goto tx_err;
+		}
 		ipproto = IPPROTO_IPV6;
 		break;
 	case htons(ETH_P_MPLS_UC):
 		ipproto = IPPROTO_MPLS;
 		break;
 	default:
+		reason = SKB_DROP_REASON_UNHANDLED_PROTO;
 		goto tx_err;
 	}
 
-	ret = ipxip6_tnl_xmit(skb, dev, ipproto);
+	ret = ipxip6_tnl_xmit(skb, dev, ipproto, &reason);
 	if (ret < 0)
 		goto tx_err;
 
@@ -1459,7 +1505,7 @@ ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)
 tx_err:
 	DEV_STATS_INC(dev, tx_errors);
 	DEV_STATS_INC(dev, tx_dropped);
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 	return NETDEV_TX_OK;
 }
 

3/2 2026/09/13 04:15 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 27273
							output: 20
							thoughts: 708
						

Thoughts:
**Analyzing the Patch Series: GRE and IP Tunneling Drop Reasons**

Okay, let's dive into this patch series. The user wants me to analyze what's going on, so let's get right to it. First, I need to understand the scope of these changes.

Alright, the diff touches a number of files: several header files (`dropreason-core.h`, `gre.h`, `ip6_tunnel.h`) and then a collection of source files within the `net/ipv4` and `net/ipv6` directories related to GRE and IP tunneling (`gre_demux.c`, `ip_gre.c`, `ip_tunnel.c`, `ip6_gre.c`, `ip6_tunnel.c`). That's a pretty clear indication it's going to affect packet handling within these tunnel types.

It looks like the core change is the introduction of a bunch of new drop reasons added to the `skb` drop reason enumeration. I see: `SKB_DROP_REASON_TNL_OPT_MISMATCH`, `SKB_DROP_REASON_TNL_OLD_SEQ`, `SKB_DROP_REASON_GRE_INVALID_HDR`, `SKB_DROP_REASON_GRE_CSUM`, `SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND`, and `SKB_DROP_REASON_TNL_ENCAP`. These are specifically related to tunneling, GRE (Generic Routing Encapsulation), and potential issues during encapsulation. Good, this is the core of the change.

Now let's check how the patch modifies the packet reception and transmission functions within IPv4/IPv6 GRE and IP tunneling. I see that `gre_parse_header` has its signature changed. `bool *csum_err` has been replaced with `enum skb_drop_reason *reason`. This is a crucial change - it means that the header parsing function is now providing a specific *reason* for parsing failures, not just a boolean error flag. This is definitely a significant improvement for debugging and identifying specific failure modes. The code then uses `kfree_skb_reason()` instead of `kfree_skb()`, which allows more precise error reporting.

I see changes across a wide array of functions: `erspan_rcv`, `__ipgre_rcv`, `ipgre_rcv`, `gre_rcv`, `gre_fb_xmit`, `erspan_fb_xmit`, `ipgre_xmit`, `erspan_xmit`, `gre_tap_xmit` in `net/ipv4/ip_gre.c`; `ip_tunnel_rcv`, `ip_md_tunnel_xmit`, `ip_tunnel_xmit` in `net/ipv4/ip_tunnel.c`; and a similar set of functions in `net/ipv6/ip6_gre.c` and `net/ipv6/ip6_tunnel.c`. It looks like these functions are being modified to incorporate the new `enum skb_drop_reason`.

Now, I want to confirm that only those callers of these specific functions have been modified. I'll need to double check other callers of `gre_parse_header` and `ip6_tnl_xmit`, just in case. Let me just grep for them across the tree and make sure nothing else breaks.



4/2 2026/09/13 04:15 tool grepper
0m Args:
{
  "Expression": "gre_parse_header\\("
}

Results:
{
  "Output": "include/net/gre.h=33=int gre_del_protocol(const struct gre_protocol *proto, u8 version);\ninclude/net/gre.h-34-\ninclude/net/gre.h:35:int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,\ninclude/net/gre.h-36-\t\t     enum skb_drop_reason *reason, __be16 proto, int nhs);\n--\nnet/ipv4/gre_demux.c=57=EXPORT_SYMBOL_GPL(gre_del_protocol);\n--\nnet/ipv4/gre_demux.c-69- */\nnet/ipv4/gre_demux.c:70:int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,\nnet/ipv4/gre_demux.c-71-\t\t     enum skb_drop_reason *reason, __be16 proto, int nhs)\n--\nnet/ipv4/ip_gre.c=219=static void gre_err(struct sk_buff *skb, u32 info)\n--\nnet/ipv4/ip_gre.c-239-\nnet/ipv4/ip_gre.c:240:\tif (gre_parse_header(skb, \u0026tpi, NULL, htons(ETH_P_IP),\nnet/ipv4/ip_gre.c-241-\t\t\t     iph-\u003eihl * 4) \u003c 0)\n--\nnet/ipv4/ip_gre.c=451=static int gre_rcv(struct sk_buff *skb)\n--\nnet/ipv4/ip_gre.c-464-\nnet/ipv4/ip_gre.c:465:\thdr_len = gre_parse_header(skb, \u0026tpi, \u0026reason, htons(ETH_P_IP), 0);\nnet/ipv4/ip_gre.c-466-\tif (hdr_len \u003c 0)\n--\nnet/ipv6/ip6_gre.c=387=static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,\n--\nnet/ipv6/ip6_gre.c-394-\nnet/ipv6/ip6_gre.c:395:\tif (gre_parse_header(skb, \u0026tpi, NULL, htons(ETH_P_IPV6),\nnet/ipv6/ip6_gre.c-396-\t\t\t     offset) \u003c 0)\n--\nnet/ipv6/ip6_gre.c=584=static int gre_rcv(struct sk_buff *skb)\n--\nnet/ipv6/ip6_gre.c-589-\nnet/ipv6/ip6_gre.c:590:\thdr_len = gre_parse_header(skb, \u0026tpi, \u0026reason, htons(ETH_P_IPV6), 0);\nnet/ipv6/ip6_gre.c-591-\tif (hdr_len \u003c 0)\n"
}

5/2 2026/09/13 04:15 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 29509
							output: 23
							thoughts: 16
						

Thoughts:
Okay, here's my interpretation of that thought process, summarized as if it were my own:

**Digging Deeper into IPv6 Tunneling**

Alright, I'm already looking at the code related to IPv6 tunneling, and to get a more comprehensive picture, I need to expand my search. I've already explored some key areas, but I should definitely broaden my scope to include the `ip6_tnl_xmit` function. This function almost certainly handles the core transmission logic for encapsulated IPv6 packets. By grepping for this, I'll hopefully find all the places it's called and referenced, which will give me valuable insights into the packet transmission flow and where potential issues might arise within the tunneling module. This will help me gain a more holistic understanding of this entire aspect of the kernel.



6/2 2026/09/13 04:15 tool grepper
0m Args:
{
  "Expression": "ip6_tnl_xmit\\("
}

Results:
{
  "Output": "include/net/ip6_tunnel.h=143=int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,\ninclude/net/ip6_tunnel.h-144-\t\t     const struct in6_addr *raddr);\ninclude/net/ip6_tunnel.h:145:int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\ninclude/net/ip6_tunnel.h-146-\t\t struct flowi6 *fl6, int encap_limit, __u32 *pmtu, __u8 proto,\n--\nnet/ipv6/ip6_gre.c=734=static netdev_tx_t __gre6_xmit(struct sk_buff *skb,\n--\nnet/ipv6/ip6_gre.c-810-\nnet/ipv6/ip6_gre.c:811:\treturn ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu,\nnet/ipv6/ip6_gre.c-812-\t\t\t    NEXTHDR_GRE, reason);\n--\nnet/ipv6/ip6_gre.c=965=static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n--\nnet/ipv6/ip6_gre.c-1133-\t}\nnet/ipv6/ip6_gre.c:1134:\terr = ip6_tnl_xmit(skb, dev, dsfield, \u0026fl6, encap_limit, \u0026mtu,\nnet/ipv6/ip6_gre.c-1135-\t\t\t   NEXTHDR_GRE, \u0026reason);\n--\nnet/ipv6/ip6_tunnel.c=1089=EXPORT_SYMBOL_GPL(ip6_tnl_xmit_ctl);\n--\nnet/ipv6/ip6_tunnel.c-1111-\nnet/ipv6/ip6_tunnel.c:1112:int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,\nnet/ipv6/ip6_tunnel.c-1113-\t\t struct flowi6 *fl6, int encap_limit, __u32 *pmtu,\n--\nnet/ipv6/ip6_tunnel.c=1329=static inline int\nnet/ipv6/ip6_tunnel.c:1330:ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,\nnet/ipv6/ip6_tunnel.c-1331-\t\tu8 protocol, enum skb_drop_reason *reason)\n--\nnet/ipv6/ip6_tunnel.c-1444-\nnet/ipv6/ip6_tunnel.c:1445:\terr = ip6_tnl_xmit(skb, dev, dsfield, \u0026fl6, encap_limit, \u0026mtu,\nnet/ipv6/ip6_tunnel.c-1446-\t\t\t   protocol, reason);\n--\nnet/ipv6/ip6_tunnel.c=1469=ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)\n--\nnet/ipv6/ip6_tunnel.c-1498-\nnet/ipv6/ip6_tunnel.c:1499:\tret = ipxip6_tnl_xmit(skb, dev, ipproto, \u0026reason);\nnet/ipv6/ip6_tunnel.c-1500-\tif (ret \u003c 0)\n"
}

7/2 2026/09/13 04:15 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 30655
							output: 21
							thoughts: 2974
						

Thoughts:
**Fuzzing Decision for the GRE Patch**

Okay, let's break this down systematically. I need to figure out if this patch is worth fuzzing, and the guidelines are very clear about that. The primary question is whether it touches reachable, executable code.

First, I need to understand what this patch actually *does*. It looks like it's adding `enum skb_drop_reason` to various `kfree_skb` calls. And it is also adding it to `gre_parse_header`. The core idea seems to be providing *reasons* for why a packet is being dropped. The guidelines say, "Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints that do not alter control flow or data structures" shouldn't be fuzzed. That's my main point of concern.

So, is adding a drop reason to a `kfree_skb` a "purely decorative" change? It sounds like it *could* be just decorative logging. However, it's *more* than just logging, it provides useful information when the packet gets dropped. Let me review the patch again to see if it is just "decorative logging".

Okay, focusing on `gre_rcv`, it uses `pskb_may_pull_reason`, which looks like a function that sets the `reason`. It's not just a print statement.  And it *changes* the control flow based on the reason. That's a key distinction.

Looking at `gre_parse_header`, it appears that the `reason` is *used* to determine if an error should be returned.  Previously, checksum failures didn't have error codes, and now this patch is adding that. Now, a checksum failure is a *reason* for a failure. This could change the control flow too. It also appears that drop reason affects what is dropped, meaning a change in behavior, and not just the packet itself.

In `ip_tunnel_rcv`, the addition of a drop reason, and a `goto drop` statement, clearly *alters* control flow. This now introduces new drop paths. This is not purely decorative.

In `ip_tunnel_xmit` the patch is changing `kfree_skb` to `kfree_skb_reason`.  And other functions such as `ipxip6_tnl_xmit` and `ip6_tnl_xmit` now use `reason` more extensively.  Now these functions explicitly pass an `enum skb_drop_reason`.

Now, reviewing the criteria, this isn't simply "decorative logging." The patch modifies control flow, introduces new error paths, and alters how the kernel handles dropped packets. Therefore, it is definitely *not* purely decorative.

This modification is *reachable executable code*, because GRE tunnels are definitely in use, and I can emulate these tunnels in my environment. And, since it changes control flow and adds new error conditions (even if those are just drop reasons), it meets the positive criteria. And since all modified code *doesn't* strictly fall under the negative criteria of "decorative logging", I'd say this patch **MUST BE FUZZED**.



8/2 2026/09/13 04:16 tool grepper
0m Args:
{
  "Expression": "kfree_skb_reason"
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 875 lines.\nUse more precise expression if possible.\n\ndrivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c=163=bool mlx5e_psp_handle_tx_skb(struct net_device *netdev,\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c-174-\tif (!psp_dev_encapsulate(net, skb, psp_st-\u003espi, psp_st-\u003ever, 0)) {\ndrivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c:175:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_PSP_OUTPUT);\ndrivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c-176-\t\tatomic_inc(\u0026priv-\u003epsp-\u003etx_drop);\n--\ndrivers/net/ipvlan/ipvlan_core.c=324=static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb,\n--\ndrivers/net/ipvlan/ipvlan_core.c-339-\t\tif (unlikely(!(dev-\u003eflags \u0026 IFF_UP))) {\ndrivers/net/ipvlan/ipvlan_core.c:340:\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);\ndrivers/net/ipvlan/ipvlan_core.c-341-\t\t\tgoto out;\n--\ndrivers/net/ipvlan/ipvlan_core.c=575=static void ipvlan_multicast_enqueue(struct ipvl_port *port,\n--\ndrivers/net/ipvlan/ipvlan_core.c-598-\t\tdev_core_stats_rx_dropped_inc(skb-\u003edev);\ndrivers/net/ipvlan/ipvlan_core.c:599:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_IPVLAN_MULTICAST_BACKLOG);\ndrivers/net/ipvlan/ipvlan_core.c-600-\t}\n--\ndrivers/net/macvlan.c=355=static void macvlan_broadcast_enqueue(struct macvlan_port *port,\n--\ndrivers/net/macvlan.c-388-free_nskb:\ndrivers/net/macvlan.c:389:\tkfree_skb_reason(nskb, SKB_DROP_REASON_MACVLAN_BROADCAST_BACKLOG);\ndrivers/net/macvlan.c-390-err:\n--\ndrivers/net/mctp/mctp-usblib.c=493=int mctp_usblib_tx_push(struct net_device *dev,\n--\ndrivers/net/mctp/mctp-usblib.c-505-\t\tmctp_usblib_tx_stats_single_drop(dev);\ndrivers/net/mctp/mctp-usblib.c:506:\t\tkfree_skb_reason(skb, reason);\ndrivers/net/mctp/mctp-usblib.c-507-\t\t/* we may still need to proceed, in case an existing ctx\n--\ndrivers/net/netdevsim/netdev.c=123=static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)\n--\ndrivers/net/netdevsim/netdev.c-180-out_drop_free:\ndrivers/net/netdevsim/netdev.c:181:\tkfree_skb_reason(skb, dr);\ndrivers/net/netdevsim/netdev.c-182-out_drop_cnt:\n--\ndrivers/net/tap.c=255=rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)\n--\ndrivers/net/tap.c-301-\t\t\t\tdrop_reason = SKB_DROP_REASON_FULL_RING;\ndrivers/net/tap.c:302:\t\t\t\tkfree_skb_reason(skb, drop_reason);\ndrivers/net/tap.c-303-\t\t\t\tkfree_skb_list_reason(next, drop_reason);\n--\ndrivers/net/tap.c-332-\t\ttap-\u003ecount_rx_dropped(tap);\ndrivers/net/tap.c:333:\tkfree_skb_reason(skb, drop_reason);\ndrivers/net/tap.c-334-\treturn RX_HANDLER_CONSUMED;\n--\ndrivers/net/tap.c=572=static ssize_t tap_get_user(struct tap_queue *q, void *msg_control,\n--\ndrivers/net/tap.c-678-err_kfree:\ndrivers/net/tap.c:679:\tkfree_skb_reason(skb, drop_reason);\ndrivers/net/tap.c-680-\n--\ndrivers/net/tun.c=1059=static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)\n--\ndrivers/net/tun.c-1163-\tskb_tx_error(skb);\ndrivers/net/tun.c:1164:\tkfree_skb_reason(skb, drop_reason);\ndrivers/net/tun.c-1165-\trcu_read_unlock();\n--\ndrivers/net/tun.c=1779=static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,\n--\ndrivers/net/tun.c-2065-\tif (!IS_ERR_OR_NULL(skb))\ndrivers/net/tun.c:2066:\t\tkfree_skb_reason(skb, drop_reason);\ndrivers/net/tun.c-2067-\n--\ndrivers/net/vxlan/vxlan_core.c=1657=static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)\n--\ndrivers/net/vxlan/vxlan_core.c-1821-\t/* Consume bad packet */\ndrivers/net/vxlan/vxlan_core.c:1822:\tkfree_skb_reason(skb, reason);\ndrivers/net/vxlan/vxlan_core.c-1823-\treturn 0;\n--\ndrivers/net/vxlan/vxlan_core.c=2284=static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,\n--\ndrivers/net/vxlan/vxlan_core.c-2310-\tif (unlikely(!(dev-\u003eflags \u0026 IFF_UP))) {\ndrivers/net/vxlan/vxlan_core.c:2311:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);\ndrivers/net/vxlan/vxlan_core.c-2312-\t\tgoto drop;\n--\ndrivers/net/vxlan/vxlan_core.c=2334=static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,\n--\ndrivers/net/vxlan/vxlan_core.c-2361-\t\t\t\t\t      VXLAN_VNI_STATS_TX_ERRORS, 0);\ndrivers/net/vxlan/vxlan_core.c:2362:\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND);\ndrivers/net/vxlan/vxlan_core.c-2363-\n--\ndrivers/net/vxlan/vxlan_core.c=2373=void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,\n--\ndrivers/net/vxlan/vxlan_core.c-2663-\tvxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);\ndrivers/net/vxlan/vxlan_core.c:2664:\tkfree_skb_reason(skb, reason);\ndrivers/net/vxlan/vxlan_core.c-2665-\treturn;\n--\ndrivers/net/vxlan/vxlan_core.c-2675-\tvxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);\ndrivers/net/vxlan/vxlan_core.c:2676:\tkfree_skb_reason(skb, reason);\ndrivers/net/vxlan/vxlan_core.c-2677-}\n--\ndrivers/net/vxlan/vxlan_core.c=2754=static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)\n--\ndrivers/net/vxlan/vxlan_core.c-2777-\t\t\telse\ndrivers/net/vxlan/vxlan_core.c:2778:\t\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_TUNNEL_TXINFO);\ndrivers/net/vxlan/vxlan_core.c-2779-\t\t\treturn NETDEV_TX_OK;\n--\ndrivers/net/vxlan/vxlan_core.c-2842-\t\t\t\t\t      VXLAN_VNI_STATS_TX_DROPS, 0);\ndrivers/net/vxlan/vxlan_core.c:2843:\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);\ndrivers/net/vxlan/vxlan_core.c-2844-\t\t\tgoto out;\n--\ndrivers/net/vxlan/vxlan_core.c-2865-\t\telse\ndrivers/net/vxlan/vxlan_core.c:2866:\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);\ndrivers/net/vxlan/vxlan_core.c-2867-\t}\n--\ndrivers/net/vxlan/vxlan_mdb.c=1702=netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan,\n--\ndrivers/net/vxlan/vxlan_mdb.c-1731-\telse\ndrivers/net/vxlan/vxlan_mdb.c:1732:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);\ndrivers/net/vxlan/vxlan_mdb.c-1733-\n--\ninclude/linux/netfilter.h=26=NF_DROP_REASON(struct sk_buff *skb, enum skb_drop_reason reason, u32 err)\n--\ninclude/linux/netfilter.h-29-\ninclude/linux/netfilter.h:30:\tkfree_skb_reason(skb, reason);\ninclude/linux/netfilter.h-31-\n--\ninclude/linux/skbuff.h=1320=static inline void\ninclude/linux/skbuff.h:1321:kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)\ninclude/linux/skbuff.h-1322-{\n--\ninclude/linux/skbuff.h=1330=static inline void kfree_skb(struct sk_buff *skb)\ninclude/linux/skbuff.h-1331-{\ninclude/linux/skbuff.h:1332:\tkfree_skb_reason(skb, SKB_DROP_REASON_NOT_SPECIFIED);\ninclude/linux/skbuff.h-1333-}\n--\ninclude/linux/skbuff.h=3464=static inline void __skb_queue_purge_reason(struct sk_buff_head *list,\n--\ninclude/linux/skbuff.h-3469-\twhile ((skb = __skb_dequeue(list)) != NULL)\ninclude/linux/skbuff.h:3470:\t\tkfree_skb_reason(skb, reason);\ninclude/linux/skbuff.h-3471-}\n--\ninclude/net/dropreason-core.h-142- *\ninclude/net/dropreason-core.h:143: * The reason of skb drop, which is used in kfree_skb_reason().\ninclude/net/dropreason-core.h-144- */\n--\ninclude/net/ip6_tunnel.h=155=static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,\n--\ninclude/net/ip6_tunnel.h-165-\t\t}\ninclude/net/ip6_tunnel.h:166:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_RECURSION_LIMIT);\ninclude/net/ip6_tunnel.h-167-\t\treturn;\n--\ninclude/net/ipv6_frag.h=65=ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)\n--\ninclude/net/ipv6_frag.h-108-\ticmpv6_send(head, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0);\ninclude/net/ipv6_frag.h:109:\tkfree_skb_reason(head, SKB_DROP_REASON_FRAG_REASM_TIMEOUT);\ninclude/net/ipv6_frag.h-110-\tgoto out_rcu_unlock;\n--\ninclude/net/sch_generic.h=1227=static inline void qdisc_dequeue_drop(struct Qdisc *q, struct sk_buff *skb,\n--\ninclude/net/sch_generic.h-1242-\t} else {\ninclude/net/sch_generic.h:1243:\t\tkfree_skb_reason(skb, (enum skb_drop_reason)reason);\ninclude/net/sch_generic.h-1244-\t}\n--\nnet/bridge/br_device.c=30=netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)\n--\nnet/bridge/br_device.c-44-\tif (unlikely(reason != SKB_NOT_DROPPED_YET)) {\nnet/bridge/br_device.c:45:\t\tkfree_skb_reason(skb, reason);\nnet/bridge/br_device.c-46-\t\treturn NETDEV_TX_OK;\n--\nnet/bridge/br_forward.c=201=void br_flood(struct net_bridge *br, struct sk_buff *skb,\n--\nnet/bridge/br_forward.c-263-\tif (!local_rcv)\nnet/bridge/br_forward.c:264:\t\tkfree_skb_reason(skb, reason);\nnet/bridge/br_forward.c-265-}\n--\nnet/bridge/br_forward.c=299=void br_multicast_flood(struct net_bridge_mdb_entry *mdst,\n--\nnet/bridge/br_forward.c-368-\tif (!local_rcv)\nnet/bridge/br_forward.c:369:\t\tkfree_skb_reason(skb, reason);\nnet/bridge/br_forward.c-370-}\n--\nnet/bridge/br_input.c=76=int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)\n--\nnet/bridge/br_input.c-239-drop:\nnet/bridge/br_input.c:240:\tkfree_skb_reason(skb, reason);\nnet/bridge/br_input.c-241-\tgoto out;\n--\nnet/bridge/br_input.c=347=static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)\n--\nnet/bridge/br_input.c-454-drop:\nnet/bridge/br_input.c:455:\t\tkfree_skb_reason(skb, reason);\nnet/bridge/br_input.c-456-\t}\n--\nnet/bridge/br_netfilter_hooks.c=376=static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_buff *skb)\n--\nnet/bridge/br_netfilter_hooks.c-400-\t\tif (reason) {\nnet/bridge/br_netfilter_hooks.c:401:\t\t\tkfree_skb_reason(skb, reason);\nnet/bridge/br_netfilter_hooks.c-402-\t\t\treturn 0;\n--\nnet/can/af_can.c=687=static int can_rcv(struct sk_buff *skb, struct net_device *dev,\n--\nnet/can/af_can.c-694-\nnet/can/af_can.c:695:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_CAN_RX_INVALID_FRAME);\nnet/can/af_can.c-696-\t\treturn NET_RX_DROP;\n--\nnet/can/af_can.c=703=static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,\n--\nnet/can/af_can.c-710-\nnet/can/af_can.c:711:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_CANFD_RX_INVALID_FRAME);\nnet/can/af_can.c-712-\t\treturn NET_RX_DROP;\n--\nnet/can/af_can.c=719=static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,\n--\nnet/can/af_can.c-726-\nnet/can/af_can.c:727:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_CANXL_RX_INVALID_FRAME);\nnet/can/af_can.c-728-\t\treturn NET_RX_DROP;\n--\nnet/core/dev.c=3511=void dev_kfree_skb_any_reason(struct sk_buff *skb, enum skb_drop_reason reason)\n--\nnet/core/dev.c-3515-\telse\nnet/core/dev.c:3516:\t\tkfree_skb_reason(skb, reason);\nnet/core/dev.c-3517-}\n--\nnet/core/dev.c=4233=static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,\n--\nnet/core/dev.c-4286-\t\t\tif (unlikely(defer_count \u003e READ_ONCE(net_hotdata.qdisc_max_burst))) {\nnet/core/dev.c:4287:\t\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_QDISC_BURST_DROP);\nnet/core/dev.c-4288-\t\t\t\treturn NET_XMIT_DROP;\n--\nnet/core/dev.c=4513=sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,\n--\nnet/core/dev.c-4555-\tcase TC_ACT_SHOT:\nnet/core/dev.c:4556:\t\tkfree_skb_reason(skb, drop_reason);\nnet/core/dev.c-4557-\t\t*ret = NET_RX_DROP;\n--\nnet/core/dev.c=4577=sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)\n--\nnet/core/dev.c-4606-\tcase TC_ACT_SHOT:\nnet/core/dev.c:4607:\t\tkfree_skb_reason(skb, drop_reason);\nnet/core/dev.c-4608-\t\t*ret = NET_XMIT_DROP;\n--\nnet/core/dev.c=4819=int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)\n--\nnet/core/dev.c-4837-\t\tdev_core_stats_tx_dropped_inc(dev);\nnet/core/dev.c:4838:\t\tkfree_skb_reason(skb, reason);\nnet/core/dev.c-4839-\t\treturn -EINVAL;\n--\nnet/core/dev.c=5429=static int enqueue_to_backlog(struct sk_buff *skb, int cpu,\n--\nnet/core/dev.c-5478-\tdev_core_stats_rx_dropped_inc(skb-\u003edev);\nnet/core/dev.c:5479:\tkfree_skb_reason(skb, reason);\nnet/core/dev.c-5480-\treturn NET_RX_DROP;\n--\nnet/core/dev.c=5718=int do_xdp_generic(const struct bpf_prog *xdp_prog, struct sk_buff **pskb)\n--\nnet/core/dev.c-5748-\tbpf_net_ctx_clear(bpf_net_ctx);\nnet/core/dev.c:5749:\tkfree_skb_reason(*pskb, SKB_DROP_REASON_XDP);\nnet/core/dev.c-5750-\treturn XDP_DROP;\n--\nnet/core/dev.c=6034=static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,\n--\nnet/core/dev.c-6237-\nnet/core/dev.c:6238:\t\tkfree_skb_reason(skb, drop_reason);\nnet/core/dev.c-6239-\t\t/* Jamal, now you will not able to escape explaining\n--\nnet/core/neighbour.c=1196=int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb,\n--\nnet/core/neighbour.c-1233-\nnet/core/neighbour.c:1234:\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_FAILED);\nnet/core/neighbour.c-1235-\t\t\treturn 1;\n--\nnet/core/neighbour.c-1255-\t\t\t\tneigh-\u003earp_queue_len_bytes -= buff-\u003etruesize;\nnet/core/neighbour.c:1256:\t\t\t\tkfree_skb_reason(buff, SKB_DROP_REASON_NEIGH_QUEUEFULL);\nnet/core/neighbour.c-1257-\t\t\t\tNEIGH_CACHE_STAT_INC(neigh-\u003etbl, unres_discards);\n--\nnet/core/neighbour.c-1277-\twrite_unlock_bh(\u0026neigh-\u003elock);\nnet/core/neighbour.c:1278:\tkfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_DEAD);\nnet/core/neighbour.c-1279-\ttrace_neigh_event_send_dead(neigh, 1);\n--\nnet/core/neighbour.c=1600=int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)\n--\nnet/core/neighbour.c-1627-\trc = -EINVAL;\nnet/core/neighbour.c:1628:\tkfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_HH_FILLFAIL);\nnet/core/neighbour.c-1629-\tgoto out;\n--\nnet/core/neighbour.c=1634=int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)\n--\nnet/core/neighbour.c-1650-\t\terr = -EINVAL;\nnet/core/neighbour.c:1651:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_HH_FILLFAIL);\nnet/core/neighbour.c-1652-\t}\n--\nnet/ipv4/arp.c=297=static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb)\n--\nnet/ipv4/arp.c-299-\tdst_link_failure(skb);\nnet/ipv4/arp.c:300:\tkfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_FAILED);\nnet/ipv4/arp.c-301-}\n--\nnet/ipv4/arp.c=970=static int arp_rcv(struct sk_buff *skb, struct net_device *dev,\n--\nnet/ipv4/arp.c-1006-freeskb:\nnet/ipv4/arp.c:1007:\tkfree_skb_reason(skb, drop_reason);\nnet/ipv4/arp.c-1008-out_of_mem:\n--\nnet/ipv4/gre_demux.c=169=static int gre_rcv(struct sk_buff *skb)\n--\nnet/ipv4/gre_demux.c-196-\tdev_core_stats_rx_nohandler_inc(skb-\u003edev);\nnet/ipv4/gre_demux.c:197:\tkfree_skb_reason(skb, SKB_DROP_REASON_UNHANDLED_PROTO);\nnet/ipv4/gre_demux.c-198-\treturn NET_RX_DROP;\n--\nnet/ipv4/gre_demux.c-200-\tdev_core_stats_rx_dropped_inc(skb-\u003edev);\nnet/ipv4/gre_demux.c:201:\tkfree_skb_reason(skb, reason);\nnet/ipv4/gre_demux.c-202-\treturn NET_RX_DROP;\n--\nnet/ipv4/icmp.c=1447=int icmp_rcv(struct sk_buff *skb)\n--\nnet/ipv4/icmp.c-1550-drop:\nnet/ipv4/icmp.c:1551:\tkfree_skb_reason(skb, reason);\nnet/ipv4/icmp.c-1552-\treturn NET_RX_DROP;\n--\nnet/ipv4/inet_fragment.c=306=inet_frag_rbtree_purge(struct rb_root *root, enum skb_drop_reason reason)\n--\nnet/ipv4/inet_fragment.c-319-\t\t\tsum += skb-\u003etruesize;\nnet/ipv4/inet_fragment.c:320:\t\t\tkfree_skb_reason(skb, reason);\nnet/ipv4/inet_fragment.c-321-\t\t\tskb = next;\n--\nnet/ipv4/ip_forward.c=83=int ip_forward(struct sk_buff *skb)\n--\nnet/ipv4/ip_forward.c-178-drop:\nnet/ipv4/ip_forward.c:179:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_forward.c-180-\treturn NET_RX_DROP;\n--\nnet/ipv4/ip_fragment.c=123=static void ip_expire(struct timer_list *t)\n--\nnet/ipv4/ip_fragment.c-191-\trcu_read_unlock();\nnet/ipv4/ip_fragment.c:192:\tkfree_skb_reason(head, reason);\nnet/ipv4/ip_fragment.c-193-\tinet_frag_putn(\u0026qp-\u003eq, refs);\n--\nnet/ipv4/ip_fragment.c=260=static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb, int *refs)\n--\nnet/ipv4/ip_fragment.c-386-err:\nnet/ipv4/ip_fragment.c:387:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_fragment.c-388-\treturn err;\n--\nnet/ipv4/ip_gre.c=267=static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,\n--\nnet/ipv4/ip_gre.c-368-drop:\nnet/ipv4/ip_gre.c:369:\tkfree_skb_reason(skb, SKB_DROP_REASON_HDR_TRUNC);\nnet/ipv4/ip_gre.c-370-\treturn PACKET_RCVD;\n--\nnet/ipv4/ip_gre.c=373=static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,\n--\nnet/ipv4/ip_gre.c-423-drop:\nnet/ipv4/ip_gre.c:424:\tkfree_skb_reason(skb, SKB_DROP_REASON_HDR_TRUNC);\nnet/ipv4/ip_gre.c-425-\treturn PACKET_RCVD;\n--\nnet/ipv4/ip_gre.c=451=static int gre_rcv(struct sk_buff *skb)\n--\nnet/ipv4/ip_gre.c-482-\tdev_core_stats_rx_dropped_inc(skb-\u003edev);\nnet/ipv4/ip_gre.c:483:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_gre.c-484-\treturn 0;\n--\nnet/ipv4/ip_gre.c=507=static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,\n--\nnet/ipv4/ip_gre.c-553-err_free_skb:\nnet/ipv4/ip_gre.c:554:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_gre.c-555-\tDEV_STATS_INC(dev, tx_dropped);\n--\nnet/ipv4/ip_gre.c=558=static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)\n--\nnet/ipv4/ip_gre.c-652-err_free_skb:\nnet/ipv4/ip_gre.c:653:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_gre.c-654-\tDEV_STATS_INC(dev, tx_dropped);\n--\nnet/ipv4/ip_gre.c=681=static netdev_tx_t ipgre_xmit(struct sk_buff *skb,\n--\nnet/ipv4/ip_gre.c-740-free_skb:\nnet/ipv4/ip_gre.c:741:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_gre.c-742-\tDEV_STATS_INC(dev, tx_dropped);\n--\nnet/ipv4/ip_gre.c=746=static netdev_tx_t erspan_xmit(struct sk_buff *skb,\n--\nnet/ipv4/ip_gre.c-807-free_skb:\nnet/ipv4/ip_gre.c:808:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_gre.c-809-\tDEV_STATS_INC(dev, tx_dropped);\n--\nnet/ipv4/ip_gre.c=813=static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,\n--\nnet/ipv4/ip_gre.c-844-free_skb:\nnet/ipv4/ip_gre.c:845:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_gre.c-846-\tDEV_STATS_INC(dev, tx_dropped);\n--\nnet/ipv4/ip_input.c=189=void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int protocol)\n--\nnet/ipv4/ip_input.c-200-\t\t\tif (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {\nnet/ipv4/ip_input.c:201:\t\t\t\tkfree_skb_reason(skb,\nnet/ipv4/ip_input.c-202-\t\t\t\t\t\t SKB_DROP_REASON_XFRM_POLICY);\n--\nnet/ipv4/ip_input.c-220-\t\t\t}\nnet/ipv4/ip_input.c:221:\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_IP_NOPROTO);\nnet/ipv4/ip_input.c-222-\t\t} else {\n--\nnet/ipv4/ip_input.c=229=static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/ip_input.c-232-\t\t__IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);\nnet/ipv4/ip_input.c:233:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);\nnet/ipv4/ip_input.c-234-\t\treturn 0;\n--\nnet/ipv4/ip_input.c=361=static int ip_rcv_finish_core(struct net *net,\n--\nnet/ipv4/ip_input.c-468-drop:\nnet/ipv4/ip_input.c:469:\tkfree_skb_reason(skb, drop_reason);\nnet/ipv4/ip_input.c-470-\treturn NET_RX_DROP;\n--\nnet/ipv4/ip_input.c=499=static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)\n--\nnet/ipv4/ip_input.c-594-drop:\nnet/ipv4/ip_input.c:595:\tkfree_skb_reason(skb, drop_reason);\nnet/ipv4/ip_input.c-596-out:\n--\nnet/ipv4/ip_output.c=199=static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/ip_output.c-243-\t\t\t    __func__);\nnet/ipv4/ip_output.c:244:\tkfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL);\nnet/ipv4/ip_output.c-245-\treturn PTR_ERR(neigh);\n--\nnet/ipv4/ip_output.c=317=static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/ip_output.c-327-\tdefault:\nnet/ipv4/ip_output.c:328:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_BPF_CGROUP_EGRESS);\nnet/ipv4/ip_output.c-329-\t\treturn ret;\n--\nnet/ipv4/ip_output.c=333=static int ip_mc_finish_output(struct net *net, struct sock *sk,\n--\nnet/ipv4/ip_output.c-347-\tdefault:\nnet/ipv4/ip_output.c:348:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_BPF_CGROUP_EGRESS);\nnet/ipv4/ip_output.c-349-\t\treturn ret;\n--\nnet/ipv4/ip_output.c=462=int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,\n--\nnet/ipv4/ip_output.c-539-\tIP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);\nnet/ipv4/ip_output.c:540:\tkfree_skb_reason(skb, SKB_DROP_REASON_IP_OUTNOROUTES);\nnet/ipv4/ip_output.c-541-\treturn -EHOSTUNREACH;\n--\nnet/ipv4/ip_tunnel.c=377=int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,\n--\nnet/ipv4/ip_tunnel.c-464-\t\tdst_release((struct dst_entry *)tun_dst);\nnet/ipv4/ip_tunnel.c:465:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_tunnel.c-466-\treturn 0;\n--\nnet/ipv4/ip_tunnel.c=580=void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n--\nnet/ipv4/ip_tunnel.c-682-kfree:\nnet/ipv4/ip_tunnel.c:683:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_tunnel.c-684-}\n--\nnet/ipv4/ip_tunnel.c=687=void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,\n--\nnet/ipv4/ip_tunnel.c-875-\t\tDEV_STATS_INC(dev, tx_dropped);\nnet/ipv4/ip_tunnel.c:876:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);\nnet/ipv4/ip_tunnel.c-877-\t\treturn;\n--\nnet/ipv4/ip_tunnel.c-891-\tDEV_STATS_INC(dev, tx_errors);\nnet/ipv4/ip_tunnel.c:892:\tkfree_skb_reason(skb, reason);\nnet/ipv4/ip_tunnel.c-893-}\n--\nnet/ipv4/ip_tunnel_core.c=50=void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,\n--\nnet/ipv4/ip_tunnel_core.c-67-\t\tip_rt_put(rt);\nnet/ipv4/ip_tunnel_core.c:68:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_RECURSION_LIMIT);\nnet/ipv4/ip_tunnel_core.c-69-\t\treturn;\n--\nnet/ipv4/ping.c=957=enum skb_drop_reason ping_rcv(struct sk_buff *skb)\n--\nnet/ipv4/ping.c-974-\nnet/ipv4/ping.c:975:\tkfree_skb_reason(skb, SKB_DROP_REASON_NO_SOCKET);\nnet/ipv4/ping.c-976-\treturn SKB_DROP_REASON_NO_SOCKET;\n--\nnet/ipv4/route.c=967=static int ip_error(struct sk_buff *skb)\n--\nnet/ipv4/route.c-1043-\nnet/ipv4/route.c:1044:out:\tkfree_skb_reason(skb, reason);\nnet/ipv4/route.c-1045-\treturn 0;\n--\nnet/ipv4/udp.c=1855=static struct sk_buff *__first_packet_length(struct sock *sk,\n--\nnet/ipv4/udp.c-1869-\t\t\t*total += skb-\u003etruesize;\nnet/ipv4/udp.c:1870:\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_UDP_CSUM);\nnet/ipv4/udp.c-1871-\t\t} else {\n--\nnet/ipv4/udp.c=2006=int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)\n--\nnet/ipv4/udp.c-2021-\t\tudp_drops_inc(sk);\nnet/ipv4/udp.c:2022:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_UDP_CSUM);\nnet/ipv4/udp.c-2023-\t\tgoto try_again;\n--\nnet/ipv4/udp.c=2044=int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)\n--\nnet/ipv4/udp.c-2137-\t}\nnet/ipv4/udp.c:2138:\tkfree_skb_reason(skb, SKB_DROP_REASON_UDP_CSUM);\nnet/ipv4/udp.c-2139-\n--\nnet/ipv6/exthdrs.c=65=static bool ip6_tlvopt_unknown(struct sk_buff *skb, int optoff,\n--\nnet/ipv6/exthdrs.c-99-drop:\nnet/ipv6/exthdrs.c:100:\tkfree_skb_reason(skb, SKB_DROP_REASON_UNHANDLED_PROTO);\nnet/ipv6/exthdrs.c-101-\treturn false;\n--\nnet/ipv6/exthdrs.c=114=static bool ip6_parse_tlv(bool hopbyhop,\n\n"
}

9/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 45017
							output: 37
							thoughts: 76
						

Thoughts:
Here's my summary, as though I'm thinking through this process:

**Diving into `kfree_skb_reason`**

Okay, so I'm looking at `kfree_skb_reason(skb, reason)`. Seems pretty straightforward: this function either passes the "reason" to the `kfree_skb` tracepoint, or it actually releases the `skb`. But I need to refresh my memory on the specifics of *how* this is handled. Alright, I know where to go... Time to check `include/linux/skbuff.h` – line 1320-ish should have the meat of it. Gotta get clear on the exact mechanism and the finer points of this.



10/2 2026/09/13 04:16 tool read-file
0m Args:
{
  "File": "include/linux/skbuff.h",
  "FirstLine": 1315,
  "LineCount": 35
}

Results:
{
  "Contents": "1315:\t\n1316:\tvoid __fix_address sk_skb_reason_drop(const struct sock *sk,\n1317:\t\t\t\t\t      struct sk_buff *skb,\n1318:\t\t\t\t\t      enum skb_drop_reason reason);\n1319:\t\n1320:\tstatic inline void\n1321:\tkfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)\n1322:\t{\n1323:\t\tsk_skb_reason_drop(NULL, skb, reason);\n1324:\t}\n1325:\t\n1326:\t/**\n1327:\t *\tkfree_skb - free an sk_buff with 'NOT_SPECIFIED' reason\n1328:\t *\t@skb: buffer to free\n1329:\t */\n1330:\tstatic inline void kfree_skb(struct sk_buff *skb)\n1331:\t{\n1332:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NOT_SPECIFIED);\n1333:\t}\n1334:\t\n1335:\tvoid skb_release_head_state(struct sk_buff *skb);\n1336:\tvoid kfree_skb_list_reason(struct sk_buff *segs,\n1337:\t\t\t\t   enum skb_drop_reason reason);\n1338:\tvoid skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt);\n1339:\tvoid skb_tx_error(struct sk_buff *skb);\n1340:\t\n1341:\tstatic inline void kfree_skb_list(struct sk_buff *segs)\n1342:\t{\n1343:\t\tkfree_skb_list_reason(segs, SKB_DROP_REASON_NOT_SPECIFIED);\n1344:\t}\n1345:\t\n1346:\t#ifdef CONFIG_TRACEPOINTS\n1347:\tvoid consume_skb(struct sk_buff *skb);\n1348:\t#else\n1349:\tstatic inline void consume_skb(struct sk_buff *skb)\n"
}

11/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 45879
							output: 22
							thoughts: 33
						

Thoughts:
Okay, let's dive into this. Here's my thought process on dissecting `sk_skb_reason_drop`:

**Analyzing `sk_skb_reason_drop`**

Alright, time to get a handle on what `sk_skb_reason_drop` actually *does*. My instinct is to start by finding where it's *used*, and the quickest way to do that in this situation is, naturally, to just `grep` for it. That should give me a good initial overview of its role within the codebase and, hopefully, reveal some context clues about how it functions. That's usually the best first step. Let's see what comes up.



12/2 2026/09/13 04:16 tool grepper
0m Args:
{
  "Expression": "sk_skb_reason_drop"
}

Results:
{
  "Output": "include/linux/skbuff.h=1298=static inline bool skb_data_unref(const struct sk_buff *skb,\n--\ninclude/linux/skbuff.h-1315-\ninclude/linux/skbuff.h:1316:void __fix_address sk_skb_reason_drop(const struct sock *sk,\ninclude/linux/skbuff.h-1317-\t\t\t\t      struct sk_buff *skb,\n--\ninclude/linux/skbuff.h=1321=kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)\ninclude/linux/skbuff.h-1322-{\ninclude/linux/skbuff.h:1323:\tsk_skb_reason_drop(NULL, skb, reason);\ninclude/linux/skbuff.h-1324-}\n--\nnet/can/bcm.c=399=static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,\n--\nnet/can/bcm.c-466-\nnet/can/bcm.c:467:\t\tsk_skb_reason_drop(sk, skb, reason);\nnet/can/bcm.c-468-\t\t/* don't care about overflows in this statistic */\n--\nnet/can/isotp.c=355=static void isotp_rcv_skb(struct sk_buff *skb, struct sock *sk)\n--\nnet/can/isotp.c-367-\tif (reason)\nnet/can/isotp.c:368:\t\tsk_skb_reason_drop(sk, skb, reason);\nnet/can/isotp.c-369-}\n--\nnet/can/j1939/socket.c=311=static void j1939_sk_recv_one(struct j1939_sock *jsk, struct sk_buff *oskb)\n--\nnet/can/j1939/socket.c-337-\tif (reason)\nnet/can/j1939/socket.c:338:\t\tsk_skb_reason_drop(\u0026jsk-\u003esk, skb, reason);\nnet/can/j1939/socket.c-339-}\n--\nnet/can/raw.c=129=static void raw_rcv(struct sk_buff *oskb, void *data)\n--\nnet/can/raw.c-211-\tif (reason)\nnet/can/raw.c:212:\t\tsk_skb_reason_drop(sk, skb, reason);\nnet/can/raw.c-213-}\n--\nnet/core/skbuff.c=1216=static __always_inline\nnet/core/skbuff.c:1217:bool __sk_skb_reason_drop(const struct sock *sk, struct sk_buff *skb,\nnet/core/skbuff.c-1218-\t\t\t  enum skb_drop_reason reason)\n--\nnet/core/skbuff.c-1235-/**\nnet/core/skbuff.c:1236: *\tsk_skb_reason_drop - free an sk_buff with special reason\nnet/core/skbuff.c-1237- *\t@sk: the socket to receive @skb, or NULL if not applicable\n--\nnet/core/skbuff.c=1245=void __fix_address\nnet/core/skbuff.c:1246:sk_skb_reason_drop(const struct sock *sk, struct sk_buff *skb,\nnet/core/skbuff.c-1247-\t\t   enum skb_drop_reason reason)\nnet/core/skbuff.c-1248-{\nnet/core/skbuff.c:1249:\tif (__sk_skb_reason_drop(sk, skb, reason))\nnet/core/skbuff.c-1250-\t\t__kfree_skb(skb);\nnet/core/skbuff.c-1251-}\nnet/core/skbuff.c:1252:EXPORT_SYMBOL(sk_skb_reason_drop);\nnet/core/skbuff.c-1253-\n--\nnet/core/skbuff.c=1282=kfree_skb_list_reason(struct sk_buff *segs, enum skb_drop_reason reason)\n--\nnet/core/skbuff.c-1290-\nnet/core/skbuff.c:1291:\t\tif (__sk_skb_reason_drop(NULL, segs, reason)) {\nnet/core/skbuff.c-1292-\t\t\tskb_poison_list(segs);\n--\nnet/core/sock.c=544=int __sk_receive_skb(struct sock *sk, struct sk_buff *skb,\n--\nnet/core/sock.c-590-discard_and_relse:\nnet/core/sock.c:591:\tsk_skb_reason_drop(sk, skb, reason);\nnet/core/sock.c-592-\tgoto out;\n--\nnet/ipv4/ping.c=931=static enum skb_drop_reason __ping_queue_rcv_skb(struct sock *sk,\n--\nnet/ipv4/ping.c-939-\tif (reason) {\nnet/ipv4/ping.c:940:\t\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv4/ping.c-941-\t\tpr_debug(\"ping_queue_rcv_skb -\u003e failed\\n\");\n--\nnet/ipv4/raw.c=302=static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/raw.c-310-\tif (reason) {\nnet/ipv4/raw.c:311:\t\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv4/raw.c-312-\t\treturn NET_RX_DROP;\n--\nnet/ipv4/raw.c=318=int raw_rcv(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/raw.c-321-\t\tsk_drops_inc(sk);\nnet/ipv4/raw.c:322:\t\tsk_skb_reason_drop(sk, skb, SKB_DROP_REASON_XFRM_POLICY);\nnet/ipv4/raw.c-323-\t\treturn NET_RX_DROP;\n--\nnet/ipv4/syncookies.c=405=struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/syncookies.c-509-out_drop:\nnet/ipv4/syncookies.c:510:\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv4/syncookies.c-511-\treturn NULL;\n--\nnet/ipv4/tcp_input.c=5297=tcp_drop_reason(struct sock *sk, struct sk_buff *skb, enum skb_drop_reason reason)\n--\nnet/ipv4/tcp_input.c-5299-\tsk_drops_skbadd(sk, skb);\nnet/ipv4/tcp_input.c:5300:\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv4/tcp_input.c-5301-}\n--\nnet/ipv4/tcp_ipv4.c=1830=int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/tcp_ipv4.c-1883-discard:\nnet/ipv4/tcp_ipv4.c:1884:\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv4/tcp_ipv4.c-1885-\t/* Be careful here. If this function gets more complicated and\n--\nnet/ipv4/tcp_ipv4.c=2070=int tcp_v4_rcv(struct sk_buff *skb)\n--\nnet/ipv4/tcp_ipv4.c-2282-\t/* Discard frame. */\nnet/ipv4/tcp_ipv4.c:2283:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv4/tcp_ipv4.c-2284-\treturn 0;\n--\nnet/ipv4/udp.c=1668=int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/udp.c-1775-\t\t\tskb_mark_not_on_list(skb);\nnet/ipv4/udp.c:1776:\t\t\tsk_skb_reason_drop(sk, skb, SKB_DROP_REASON_PROTO_MEM);\nnet/ipv4/udp.c-1777-\t\t}\n--\nnet/ipv4/udp.c=2320=static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/udp.c-2346-\t\ttrace_udp_fail_queue_rcv_skb(rc, sk, skb);\nnet/ipv4/udp.c:2347:\t\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv4/udp.c-2348-\t\treturn -1;\n--\nnet/ipv4/udp.c=2362=static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/udp.c-2430-\tudp_drops_inc(sk);\nnet/ipv4/udp.c:2431:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv4/udp.c-2432-\treturn -1;\n--\nnet/ipv4/udp.c=2603=int udp_rcv(struct sk_buff *skb)\n--\nnet/ipv4/udp.c-2683-\t */\nnet/ipv4/udp.c:2684:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv4/udp.c-2685-\treturn 0;\n--\nnet/ipv4/udp.c-2706-\t__UDP_INC_STATS(net, UDP_MIB_INERRORS);\nnet/ipv4/udp.c:2707:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv4/udp.c-2708-\treturn 0;\n--\nnet/ipv6/inet6_connection_sock.c=97=int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused)\n--\nnet/ipv6/inet6_connection_sock.c-109-\t\t\tsk-\u003esk_route_caps = 0;\nnet/ipv6/inet6_connection_sock.c:110:\t\t\tsk_skb_reason_drop(sk, skb,\nnet/ipv6/inet6_connection_sock.c-111-\t\t\t\t\t   SKB_DROP_REASON_IP_OUTNOROUTES);\n--\nnet/ipv6/ip6mr.c=1089=static int ip6mr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt,\n--\nnet/ipv6/ip6mr.c-1174-\tif (reason) {\nnet/ipv6/ip6mr.c:1175:\t\tsk_skb_reason_drop(mroute6_sk, skb, reason);\nnet/ipv6/ip6mr.c-1176-\t\treturn -ENOMEM;\n--\nnet/ipv6/raw.c=359=static inline int rawv6_rcv_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv6/raw.c-365-\t\tsk_drops_inc(sk);\nnet/ipv6/raw.c:366:\t\tsk_skb_reason_drop(sk, skb, SKB_DROP_REASON_SKB_CSUM);\nnet/ipv6/raw.c-367-\t\treturn NET_RX_DROP;\n--\nnet/ipv6/raw.c-373-\tif (reason) {\nnet/ipv6/raw.c:374:\t\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv6/raw.c-375-\t\treturn NET_RX_DROP;\n--\nnet/ipv6/raw.c=388=int rawv6_rcv(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv6/raw.c-394-\t\tsk_drops_inc(sk);\nnet/ipv6/raw.c:395:\t\tsk_skb_reason_drop(sk, skb, SKB_DROP_REASON_XFRM_POLICY);\nnet/ipv6/raw.c-396-\t\treturn NET_RX_DROP;\n--\nnet/ipv6/raw.c-419-\t\t\tsk_drops_inc(sk);\nnet/ipv6/raw.c:420:\t\t\tsk_skb_reason_drop(sk, skb, SKB_DROP_REASON_SKB_CSUM);\nnet/ipv6/raw.c-421-\t\t\treturn NET_RX_DROP;\n--\nnet/ipv6/syncookies.c=174=struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv6/syncookies.c-286-out_drop:\nnet/ipv6/syncookies.c:287:\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv6/syncookies.c-288-\treturn NULL;\n--\nnet/ipv6/tcp_ipv6.c=847=static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 seq,\n--\nnet/ipv6/tcp_ipv6.c-1001-\nnet/ipv6/tcp_ipv6.c:1002:\tsk_skb_reason_drop(sk, buff, SKB_DROP_REASON_IP_OUTNOROUTES);\nnet/ipv6/tcp_ipv6.c-1003-}\n--\nnet/ipv6/tcp_ipv6.c=1567=int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv6/tcp_ipv6.c-1662-\t\t__kfree_skb(opt_skb);\nnet/ipv6/tcp_ipv6.c:1663:\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv6/tcp_ipv6.c-1664-\treturn 0;\n--\nnet/ipv6/tcp_ipv6.c=1730=INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)\n--\nnet/ipv6/tcp_ipv6.c-1935-\tSKB_DR_OR(drop_reason, NOT_SPECIFIED);\nnet/ipv6/tcp_ipv6.c:1936:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv6/tcp_ipv6.c-1937-\treturn 0;\n--\nnet/ipv6/udp.c=779=static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv6/udp.c-805-\t\ttrace_udp_fail_queue_rcv_skb(rc, sk, skb);\nnet/ipv6/udp.c:806:\t\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv6/udp.c-807-\t\treturn -1;\n--\nnet/ipv6/udp.c=813=static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv6/udp.c-879-\tudp_drops_inc(sk);\nnet/ipv6/udp.c:880:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/ipv6/udp.c-881-\treturn -1;\n--\nnet/ipv6/udp.c=1076=INDIRECT_CALLABLE_SCOPE int udpv6_rcv(struct sk_buff *skb)\n--\nnet/ipv6/udp.c-1169-\nnet/ipv6/udp.c:1170:\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv6/udp.c-1171-\treturn 0;\n--\nnet/ipv6/udp.c-1189-\t__UDP6_INC_STATS(net, UDP_MIB_INERRORS);\nnet/ipv6/udp.c:1190:\tsk_skb_reason_drop(sk, skb, reason);\nnet/ipv6/udp.c-1191-\treturn 0;\n--\nnet/packet/af_packet.c=2136=static int packet_rcv(struct sk_buff *skb, struct net_device *dev,\n--\nnet/packet/af_packet.c-2244-drop:\nnet/packet/af_packet.c:2245:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/packet/af_packet.c-2246-\treturn 0;\n--\nnet/packet/af_packet.c=2249=static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,\n--\nnet/packet/af_packet.c-2517-drop:\nnet/packet/af_packet.c:2518:\tsk_skb_reason_drop(sk, skb, drop_reason);\nnet/packet/af_packet.c-2519-\treturn 0;\n--\nnet/packet/af_packet.c-2526-\tsk-\u003esk_data_ready(sk);\nnet/packet/af_packet.c:2527:\tsk_skb_reason_drop(sk, copy_skb, drop_reason);\nnet/packet/af_packet.c-2528-\tgoto drop_n_restore;\n--\nnet/psp/psp_sock.c=30=psp_validate_xmit(struct sock *sk, struct net_device *dev, struct sk_buff *skb)\n--\nnet/psp/psp_sock.c-39-\tif (!good) {\nnet/psp/psp_sock.c:40:\t\tsk_skb_reason_drop(sk, skb, SKB_DROP_REASON_PSP_OUTPUT);\nnet/psp/psp_sock.c-41-\t\treturn NULL;\n"
}

13/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 50975
							output: 37
							thoughts: 18
						

Thoughts:
Here's a summary of my thought process, as if I were analyzing that function:

**Diving into `__sk_skb_reason_drop`**

Alright, let's dissect this `__sk_skb_reason_drop` function. Based on the name alone, it's pretty clear that this handles the dropping of an skb (Socket Buffer), and the "reason" part hints that it's about logging *why* the packet is being discarded. As a network expert, I already have a mental model of how skbs work, and the significance of packet drops in a network stack. I'm expecting this function to be critical for debugging network performance issues, security breaches, and identifying bottlenecks.

I want to know how granular the logging is. Does it track specific error conditions? Are there performance metrics involved, or is it more of a diagnostic tool? I'm hoping it provides insights into packet loss beyond a simple "dropped" message. I need to understand what information it captures and how that information is handled - is it going to a log file, a ring buffer, or something else entirely? A detailed trace would be incredibly useful for deeper analysis. I'll need to know which fields within the skb are accessed, or modified. I'm already formulating questions about the potential impact on the overall performance of the system if this function is frequently called. Time to dig in and see the implementation details!



14/2 2026/09/13 04:16 tool read-file
0m Args:
{
  "File": "net/core/skbuff.c",
  "FirstLine": 1216,
  "LineCount": 35
}

Results:
{
  "Contents": "1216:\tstatic __always_inline\n1217:\tbool __sk_skb_reason_drop(const struct sock *sk, struct sk_buff *skb,\n1218:\t\t\t\t  enum skb_drop_reason reason)\n1219:\t{\n1220:\t\tif (unlikely(!skb_unref(skb)))\n1221:\t\t\treturn false;\n1222:\t\n1223:\t\tDEBUG_NET_WARN_ON_ONCE(reason == SKB_NOT_DROPPED_YET ||\n1224:\t\t\t\t       u32_get_bits(reason,\n1225:\t\t\t\t\t\t    SKB_DROP_REASON_SUBSYS_MASK) \u003e=\n1226:\t\t\t\t\tSKB_DROP_REASON_SUBSYS_NUM);\n1227:\t\n1228:\t\tif (reason == SKB_CONSUMED)\n1229:\t\t\ttrace_consume_skb(skb, __builtin_return_address(0));\n1230:\t\telse\n1231:\t\t\ttrace_kfree_skb(skb, __builtin_return_address(0), reason, sk);\n1232:\t\treturn true;\n1233:\t}\n1234:\t\n1235:\t/**\n1236:\t *\tsk_skb_reason_drop - free an sk_buff with special reason\n1237:\t *\t@sk: the socket to receive @skb, or NULL if not applicable\n1238:\t *\t@skb: buffer to free\n1239:\t *\t@reason: reason why this skb is dropped\n1240:\t *\n1241:\t *\tDrop a reference to the buffer and free it if the usage count has hit\n1242:\t *\tzero. Meanwhile, pass the receiving socket and drop reason to\n1243:\t *\t'kfree_skb' tracepoint.\n1244:\t */\n1245:\tvoid __fix_address\n1246:\tsk_skb_reason_drop(const struct sock *sk, struct sk_buff *skb,\n1247:\t\t\t   enum skb_drop_reason reason)\n1248:\t{\n1249:\t\tif (__sk_skb_reason_drop(sk, skb, reason))\n1250:\t\t\t__kfree_skb(skb);\n"
}

15/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 51938
							output: 22
							thoughts: 1292
						

Thoughts:
**Analyzing the kfree_skb_reason Patch: A Detailed Examination**

Okay, so I'm looking at this `__sk_skb_reason_drop` function, and it's pretty straightforward, line 1223 says it traces the drop reason. But, I need to know *what* changed, not just *that* it's tracing. So, I see that this patch introduces `kfree_skb_reason` which traces the drop reason, but I need to dive deeper. Did the *control flow* actually *change*? Let's verify every single file this touches.

First, I see additions to `include/net/dropreason-core.h`. Several new enum values were added to `enum skb_drop_reason` and `FN(...)`: `TNL_OPT_MISMATCH`, `TNL_OLD_SEQ`, `GRE_INVALID_HDR`, `GRE_CSUM`, `GRE_TUNNEL_NOT_FOUND`, and `TNL_ENCAP`. Okay, noted. This expands the possible drop reasons.

Next, `include/net/gre.h` and `include/net/ip6_tunnel.h` have function signatures updated: `gre_parse_header` and `ip6_tnl_xmit` now take an `enum skb_drop_reason *reason`. This *suggests* that these functions might now be setting a reason when an error occurs, and I need to confirm the use of this parameter.

Now, let's get into the code, starting with `net/ipv4/gre_demux.c`. I have to be thorough here. Looking at the `gre_parse_header` function, it seems the major change is the introduction of a `reason` parameter. Before, if a checksum failed, the code might return `-EINVAL`. Now, if a `reason` pointer is passed, and a checksum fails, it sets `*reason = SKB_DROP_REASON_GRE_CSUM;` and returns `-EINVAL`. If the `reason` is NULL, the flow is *exactly* the same as before. So, in *this* function, the control flow is the *same* when the reason parameter is NULL. Now I must confirm what the value of reason is, and how it is used.

I need to confirm all uses of this parameter, or I may be missing something.

Next, I look at `gre_rcv` in `net/ipv4/gre_demux.c`. Ah, here's a definite change. `pskb_may_pull` is replaced by `pskb_may_pull_reason`, and `kfree_skb` is replaced by `kfree_skb_reason`. I need to figure out how `pskb_may_pull_reason` works. Let me confirm what `pskb_may_pull_reason` does.



16/2 2026/09/13 04:16 tool grepper
0m Args:
{
  "Expression": "pskb_may_pull_reason"
}

Results:
{
  "Output": "drivers/net/vxlan/vxlan_core.c=1548=static enum skb_drop_reason vxlan_remcsum(struct sk_buff *skb, u32 vxflags)\n--\ndrivers/net/vxlan/vxlan_core.c-1559-\ndrivers/net/vxlan/vxlan_core.c:1560:\treason = pskb_may_pull_reason(skb, offset + sizeof(u16));\ndrivers/net/vxlan/vxlan_core.c-1561-\tif (reason)\n--\ndrivers/net/vxlan/vxlan_core.c=1657=static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)\n--\ndrivers/net/vxlan/vxlan_core.c-1672-\t/* Need UDP and VXLAN header to be present */\ndrivers/net/vxlan/vxlan_core.c:1673:\treason = pskb_may_pull_reason(skb, VXLAN_HLEN);\ndrivers/net/vxlan/vxlan_core.c-1674-\tif (reason)\n--\ninclude/linux/skbuff.h=2861=static __always_inline enum skb_drop_reason\ninclude/linux/skbuff.h:2862:pskb_may_pull_reason(struct sk_buff *skb, unsigned int len)\ninclude/linux/skbuff.h-2863-{\n--\ninclude/linux/skbuff.h=2880=pskb_may_pull(struct sk_buff *skb, unsigned int len)\ninclude/linux/skbuff.h-2881-{\ninclude/linux/skbuff.h:2882:\treturn pskb_may_pull_reason(skb, len) == SKB_NOT_DROPPED_YET;\ninclude/linux/skbuff.h-2883-}\n--\ninclude/linux/skbuff.h=3292=pskb_network_may_pull_reason(struct sk_buff *skb, unsigned int len)\ninclude/linux/skbuff.h-3293-{\ninclude/linux/skbuff.h:3294:\treturn pskb_may_pull_reason(skb, skb_network_offset(skb) + len);\ninclude/linux/skbuff.h-3295-}\n--\ninclude/net/ip_tunnels.h=494=skb_vlan_inet_prepare(struct sk_buff *skb, bool inner_proto_inherit)\n--\ninclude/net/ip_tunnels.h-518-\t */\ninclude/net/ip_tunnels.h:519:\treason = pskb_may_pull_reason(skb, maclen + nhlen);\ninclude/net/ip_tunnels.h-520-\tif (reason)\n--\nnet/bridge/br_device.c=30=netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)\nnet/bridge/br_device.c-31-{\nnet/bridge/br_device.c:32:\tenum skb_drop_reason reason = pskb_may_pull_reason(skb, ETH_HLEN);\nnet/bridge/br_device.c-33-\tstruct net_bridge_mcast_port *pmctx_null = NULL;\n--\nnet/core/filter.c=1681=static inline int __bpf_try_make_writable(struct sk_buff *skb,\n--\nnet/core/filter.c-1684-#ifdef CONFIG_DEBUG_NET\nnet/core/filter.c:1685:\t/* Avoid a splat in pskb_may_pull_reason() */\nnet/core/filter.c-1686-\tif (write_len \u003e INT_MAX)\n--\nnet/ipv4/arp.c=970=static int arp_rcv(struct sk_buff *skb, struct net_device *dev,\n--\nnet/ipv4/arp.c-986-\t/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */\nnet/ipv4/arp.c:987:\tdrop_reason = pskb_may_pull_reason(skb, arp_hdr_len(dev));\nnet/ipv4/arp.c-988-\tif (drop_reason != SKB_NOT_DROPPED_YET)\n--\nnet/ipv4/gre_demux.c=169=static int gre_rcv(struct sk_buff *skb)\n--\nnet/ipv4/gre_demux.c-175-\nnet/ipv4/gre_demux.c:176:\treason = pskb_may_pull_reason(skb, 12);\nnet/ipv4/gre_demux.c-177-\tif (reason)\n--\nnet/ipv4/ip_gre.c=681=static netdev_tx_t ipgre_xmit(struct sk_buff *skb,\n--\nnet/ipv4/ip_gre.c-705-\nnet/ipv4/ip_gre.c:706:\t\treason = pskb_may_pull_reason(skb, pull_len);\nnet/ipv4/ip_gre.c-707-\t\tif (reason)\n--\nnet/ipv6/icmp.c=1037=enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type,\n--\nnet/ipv6/icmp.c-1047-\nnet/ipv6/icmp.c:1048:\treason = pskb_may_pull_reason(skb, sizeof(struct ipv6hdr));\nnet/ipv6/icmp.c-1049-\tif (reason != SKB_NOT_DROPPED_YET)\n--\nnet/ipv6/icmp.c-1067-\t/* Checkin header including 8 bytes of inner protocol header. */\nnet/ipv6/icmp.c:1068:\treason = pskb_may_pull_reason(skb, inner_offset + 8);\nnet/ipv6/icmp.c-1069-\tif (reason != SKB_NOT_DROPPED_YET)\n--\nnet/ipv6/ip6_tunnel.c=808=static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,\n--\nnet/ipv6/ip6_tunnel.c-848-\tif (tunnel-\u003edev-\u003etype == ARPHRD_ETHER) {\nnet/ipv6/ip6_tunnel.c:849:\t\treason = pskb_may_pull_reason(skb, ETH_HLEN);\nnet/ipv6/ip6_tunnel.c-850-\t\tif (reason) {\n"
}

17/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 55597
							output: 24
							thoughts: 125
						

Thoughts:
**Decoding this Conditional Logic**

Okay, let's break this down. It looks like we're dealing with a conditional statement related to network packet handling, specifically within the kernel. The expression `pskb_may_pull(skb, len)` is key here. It seems to be a function call, likely determining whether we *can* safely pull data from a `skb` (socket buffer) of a given `len`.

The first thing to note is that `pskb_may_pull(skb, len)` evaluates to `pskb_may_pull_reason(skb, len) == SKB_NOT_DROPPED_YET`. And `SKB_NOT_DROPPED_YET` is equal to 0. So, `pskb_may_pull` must return `false` if `pskb_may_pull_reason` returns anything *other* than zero.

The confusing part is this conditional: `if (reason)`. Based on that earlier reasoning, this is true when `pskb_may_pull` is `false`. So `reason` here is actually the *reason* why the pull *shouldn't* happen.

Alright, I need to get to the bottom of how this works. I wonder what the `pskb_inet_may_pull_reason` function does. I'm going to quickly check how that function is used to understand the wider context. I'll just run a `grep` and see where that function is actually getting called.



18/2 2026/09/13 04:16 tool grepper
0m Args:
{
  "Expression": "pskb_inet_may_pull_reason"
}

Results:
{
  "Output": "drivers/net/vxlan/vxlan_core.c=1657=static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)\n--\ndrivers/net/vxlan/vxlan_core.c-1778-\ndrivers/net/vxlan/vxlan_core.c:1779:\treason = pskb_inet_may_pull_reason(skb);\ndrivers/net/vxlan/vxlan_core.c-1780-\tif (reason) {\n--\ninclude/net/ip_tunnels.h=465=static inline enum skb_drop_reason\ninclude/net/ip_tunnels.h:466:pskb_inet_may_pull_reason(struct sk_buff *skb)\ninclude/net/ip_tunnels.h-467-{\n--\ninclude/net/ip_tunnels.h=486=static inline bool pskb_inet_may_pull(struct sk_buff *skb)\ninclude/net/ip_tunnels.h-487-{\ninclude/net/ip_tunnels.h:488:\treturn pskb_inet_may_pull_reason(skb) == SKB_NOT_DROPPED_YET;\ninclude/net/ip_tunnels.h-489-}\n--\nnet/ipv4/ip_gre.c=681=static netdev_tx_t ipgre_xmit(struct sk_buff *skb,\n--\nnet/ipv4/ip_gre.c-688-\nnet/ipv4/ip_gre.c:689:\treason = pskb_inet_may_pull_reason(skb);\nnet/ipv4/ip_gre.c-690-\tif (reason)\n--\nnet/ipv4/ip_gre.c=746=static netdev_tx_t erspan_xmit(struct sk_buff *skb,\n--\nnet/ipv4/ip_gre.c-754-\nnet/ipv4/ip_gre.c:755:\treason = pskb_inet_may_pull_reason(skb);\nnet/ipv4/ip_gre.c-756-\tif (reason)\n--\nnet/ipv4/ip_gre.c=813=static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,\n--\nnet/ipv4/ip_gre.c-819-\nnet/ipv4/ip_gre.c:820:\treason = pskb_inet_may_pull_reason(skb);\nnet/ipv4/ip_gre.c-821-\tif (reason)\n--\nnet/ipv4/ip_tunnel.c=377=int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,\n--\nnet/ipv4/ip_tunnel.c-424-\nnet/ipv4/ip_tunnel.c:425:\treason = pskb_inet_may_pull_reason(skb);\nnet/ipv4/ip_tunnel.c-426-\tif (reason) {\n--\nnet/ipv6/ip6_gre.c=918=static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,\n--\nnet/ipv6/ip6_gre.c-926-\nnet/ipv6/ip6_gre.c:927:\treason = pskb_inet_may_pull_reason(skb);\nnet/ipv6/ip6_gre.c-928-\tif (reason)\n--\nnet/ipv6/ip6_gre.c=965=static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,\n--\nnet/ipv6/ip6_gre.c-981-\nnet/ipv6/ip6_gre.c:982:\treason = pskb_inet_may_pull_reason(skb);\nnet/ipv6/ip6_gre.c-983-\tif (reason)\n--\nnet/ipv6/ip6_tunnel.c=1469=ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev)\n--\nnet/ipv6/ip6_tunnel.c-1475-\nnet/ipv6/ip6_tunnel.c:1476:\treason = pskb_inet_may_pull_reason(skb);\nnet/ipv6/ip6_tunnel.c-1477-\tif (reason)\n"
}

19/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 57222
							output: 38
							thoughts: 171
						

Thoughts:
**Analyzing the Code's Logic**

Okay, let's break this down. It looks like I'm looking at a piece of code that's been simplified, specifically around the `pskb_inet_may_pull` function. I see that the original check, `if (!pskb_inet_may_pull(skb))`, essentially translates to checking if `pskb_inet_may_pull_reason(skb)` is *not* equal to `SKB_NOT_DROPPED_YET`. Now, the change has `reason = pskb_inet_may_pull_reason(skb); if (reason)`. That seems functionally equivalent... a little cleaner, maybe? But I always like to double-check these things.

Now, I'm getting a little curious. I wonder how the `skb_vlan_inet_prepare` function factors into this. I'm going to quickly check `include/net/ip_tunnels.h` around line 494. See if there are any subtle interactions to consider. Just gotta make sure this simplification hasn't introduced an edge case I'm missing. Time to dive into the includes.



20/2 2026/09/13 04:16 tool read-file
0m Args:
{
  "File": "include/net/ip_tunnels.h",
  "FirstLine": 494,
  "LineCount": 35
}

Results:
{
  "Contents": " 494:\tskb_vlan_inet_prepare(struct sk_buff *skb, bool inner_proto_inherit)\n 495:\t{\n 496:\t\tint nhlen = 0, maclen = inner_proto_inherit ? 0 : ETH_HLEN;\n 497:\t\t__be16 type = skb-\u003eprotocol;\n 498:\t\tenum skb_drop_reason reason;\n 499:\t\n 500:\t\t/* Essentially this is skb_protocol(skb, true)\n 501:\t\t * And we get MAC len.\n 502:\t\t */\n 503:\t\tif (eth_type_vlan(type))\n 504:\t\t\ttype = __vlan_get_protocol(skb, type, \u0026maclen);\n 505:\t\n 506:\t\tswitch (type) {\n 507:\t#if IS_ENABLED(CONFIG_IPV6)\n 508:\t\tcase htons(ETH_P_IPV6):\n 509:\t\t\tnhlen = sizeof(struct ipv6hdr);\n 510:\t\t\tbreak;\n 511:\t#endif\n 512:\t\tcase htons(ETH_P_IP):\n 513:\t\t\tnhlen = sizeof(struct iphdr);\n 514:\t\t\tbreak;\n 515:\t\t}\n 516:\t\t/* For ETH_P_IPV6/ETH_P_IP we make sure to pull\n 517:\t\t * a base network header in skb-\u003ehead.\n 518:\t\t */\n 519:\t\treason = pskb_may_pull_reason(skb, maclen + nhlen);\n 520:\t\tif (reason)\n 521:\t\t\treturn reason;\n 522:\t\n 523:\t\tskb_set_network_header(skb, maclen);\n 524:\t\n 525:\t\treturn SKB_NOT_DROPPED_YET;\n 526:\t}\n 527:\t\n 528:\tstatic inline int ip_encap_hlen(struct ip_tunnel_encap *e)\n"
}

21/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 58235
							output: 38
							thoughts: 1645
						

Thoughts:
**Analyzing the Patch for Fuzzing Worthiness**

Okay, so I'm looking at this patch and my initial thought was about how the code was modified with `skb_vlan_inet_prepare`. It seems like the control flow is the same, just with the return value now being assigned to a `reason` variable, but that's a red herring. The real question is, is this modification worth fuzzing?

I need to re-evaluate based on the fuzzing criteria, specifically the *negative* criteria for when a change is *not* worth fuzzing. I need to make sure I don't waste time on a change that, by design, won't yield meaningful results.

Specifically, I'm drawn to the "Purely decorative logging" bullet point.  My initial reaction is that passing `enum skb_drop_reason` to `kfree_skb_reason` *feels* like decorative logging.  After all, `kfree_skb_reason` just calls `trace_kfree_skb`, and tracing in general doesn't change control flow *or* data structures, so it doesn't affect the compiled kernel image. However, the wording there is key, tracing is considered *purely decorative* if it "does not alter control flow or data structures," I need to make sure this is actually true. I must carefully consider if this particular usage of `reason` changes anything.

So, I need to look into this function, and see if I am misinterpreting the requirements.

I went back and analyzed the modified functions, starting with `net/ipv4/gre_demux.c`. The changes to `gre_parse_header` involve setting `reason` when returning an error. It's still returning `-EINVAL`, but it's now also setting a `reason` code. However, the rest of the file also includes other places that add a `reason` variable, which might change control flow.

Now, I look at `net/ipv4/ip_tunnel.c`. The most notable change involves splitting a combined `if` statement into two, now with unique drop reasons.  The original code had an `if` that checked two conditions, both leading to the same `goto drop`. The new version separates the conditions into two `if` statements, each assigning a different `SKB_DROP_REASON` before the `goto drop`. I can confirm this doesn't change the control flow because both increment the same stats and both `goto drop`. The original function was equivalent in control flow to `if (cond1) { goto drop; } else if (cond2) { goto drop; }`, the new one is equivalent to `if (cond1) { goto drop; } if (cond2) { goto drop; }`.

I look at `ip_tunnel_xmit` now and see that if `!skb_dst(skb)`, the code now assigns `SKB_DROP_REASON_NO_TX_TARGET` before going to `tx_error`. There is some additional control flow logic added, to set a default drop reason.

Okay, I think I've got it. The key is in these added `reason` variables and calls to `kfree_skb_reason`.  The change itself isn't *purely* decorative. It *is* adding a finer-grained set of reasons *when* an error occurs, but the control flow is identical to the prior logic. It's essentially adding more debugging information, and making it easier to determine the cause of the drop during debugging/testing/etc. Since the execution path that calls `kfree_skb_reason` does not modify control flow, the changes here are not worth fuzzing.



22/2 2026/09/13 04:16 tool read-file
0m Args:
{
  "File": "net/ipv4/ip_tunnel.c",
  "FirstLine": 700,
  "LineCount": 70
}

Results:
{
  "Contents": " 700:\t\tbool connected;\n 701:\t\tint err_count;\n 702:\t\tu8 tos, ttl;\n 703:\t\t__be32 dst;\n 704:\t\t__be16 df;\n 705:\t\n 706:\t\tinner_iph = (const struct iphdr *)skb_inner_network_header(skb);\n 707:\t\tconnected = (tunnel-\u003eparms.iph.daddr != 0);\n 708:\t\tpayload_protocol = skb_protocol(skb, true);\n 709:\t\n 710:\t\tmemset(\u0026(IPCB(skb)-\u003eopt), 0, sizeof(IPCB(skb)-\u003eopt));\n 711:\t\n 712:\t\tdst = tnl_params-\u003edaddr;\n 713:\t\tif (dst == 0) {\n 714:\t\t\t/* NBMA tunnel */\n 715:\t\n 716:\t\t\tif (!skb_dst(skb)) {\n 717:\t\t\t\tDEV_STATS_INC(dev, tx_fifo_errors);\n 718:\t\t\t\treason = SKB_DROP_REASON_NO_TX_TARGET;\n 719:\t\t\t\tgoto tx_error;\n 720:\t\t\t}\n 721:\t\n 722:\t\t\t/* Only the branches below can derive a destination.  If\n 723:\t\t\t * none of them matches, the payload protocol is not one\n 724:\t\t\t * this tunnel can carry.\n 725:\t\t\t */\n 726:\t\t\treason = SKB_DROP_REASON_UNHANDLED_PROTO;\n 727:\t\t\ttun_info = skb_tunnel_info(skb);\n 728:\t\t\tif (tun_info \u0026\u0026 (tun_info-\u003emode \u0026 IP_TUNNEL_INFO_TX) \u0026\u0026\n 729:\t\t\t    ip_tunnel_info_af(tun_info) == AF_INET \u0026\u0026\n 730:\t\t\t    tun_info-\u003ekey.u.ipv4.dst) {\n 731:\t\t\t\tdst = tun_info-\u003ekey.u.ipv4.dst;\n 732:\t\t\t\tmd = true;\n 733:\t\t\t\tconnected = true;\n 734:\t\t\t} else if (payload_protocol == htons(ETH_P_IP)) {\n 735:\t\t\t\trt = skb_rtable(skb);\n 736:\t\t\t\tdst = rt_nexthop(rt, inner_iph-\u003edaddr);\n 737:\t\t\t}\n 738:\t#if IS_ENABLED(CONFIG_IPV6)\n 739:\t\t\telse if (payload_protocol == htons(ETH_P_IPV6)) {\n 740:\t\t\t\tconst struct in6_addr *addr6;\n 741:\t\t\t\tstruct neighbour *neigh;\n 742:\t\t\t\tbool do_tx_error_icmp;\n 743:\t\t\t\tint addr_type;\n 744:\t\n 745:\t\t\t\tneigh = dst_neigh_lookup(skb_dst(skb),\n 746:\t\t\t\t\t\t\t \u0026ipv6_hdr(skb)-\u003edaddr);\n 747:\t\t\t\tif (!neigh) {\n 748:\t\t\t\t\treason = SKB_DROP_REASON_NEIGH_CREATEFAIL;\n 749:\t\t\t\t\tgoto tx_error;\n 750:\t\t\t\t}\n 751:\t\n 752:\t\t\t\taddr6 = (const struct in6_addr *)\u0026neigh-\u003eprimary_key;\n 753:\t\t\t\taddr_type = ipv6_addr_type(addr6);\n 754:\t\n 755:\t\t\t\tif (addr_type == IPV6_ADDR_ANY) {\n 756:\t\t\t\t\taddr6 = \u0026ipv6_hdr(skb)-\u003edaddr;\n 757:\t\t\t\t\taddr_type = ipv6_addr_type(addr6);\n 758:\t\t\t\t}\n 759:\t\n 760:\t\t\t\tif ((addr_type \u0026 IPV6_ADDR_COMPATv4) == 0)\n 761:\t\t\t\t\tdo_tx_error_icmp = true;\n 762:\t\t\t\telse {\n 763:\t\t\t\t\tdo_tx_error_icmp = false;\n 764:\t\t\t\t\tdst = addr6-\u003es6_addr32[3];\n 765:\t\t\t\t}\n 766:\t\t\t\tneigh_release(neigh);\n 767:\t\t\t\tif (do_tx_error_icmp) {\n 768:\t\t\t\t\treason = SKB_DROP_REASON_NO_TX_TARGET;\n 769:\t\t\t\t\tgoto tx_error_icmp;\n"
}

23/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 61861
							output: 25
							thoughts: 85
						

Thoughts:
**Analyzing a Network Patch**

Okay, here's the deal. I'm looking at this patch and, right off the bat, it's pretty focused: "net: annotate skb drop reasons in ip_tunnel, gre, ip6_tunnel, ip6_gre." My initial reaction? This is good, this is helpful. We're getting more granular information on *why* packets are being dropped, specifically within these tunneling protocols.

Now, my mind starts racing. I need context. I'm thinking, "Is this consistent with the existing drop reason annotations?" I'll immediately dive into the commit message to see if it explains the rationale, maybe mentions performance improvements, or ties to a specific bug report. I'll probably also look at the author's other commits and what they've done in this area. To fully understand it I need to see if this commit introduces new drop reasons, builds upon existing conventions, or refactors previous efforts.

I'm also going to *grep* through the codebase, searching for similar commits that add drop reasons. This will give me a point of comparison – a sort of 'pattern' recognition exercise. How are these reasons formatted? What level of detail is typical? Are there any common practices that this patch is adhering to or deviating from? I want to assess the quality and consistency of this work and how it fits into the broader picture. This will help me validate the new patch.



24/2 2026/09/13 04:16 tool grepper
0m Args:
{
  "Expression": "SKB_DROP_REASON_PSP_OUTPUT"
}

Results:
{
  "Output": "drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c=163=bool mlx5e_psp_handle_tx_skb(struct net_device *netdev,\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c-174-\tif (!psp_dev_encapsulate(net, skb, psp_st-\u003espi, psp_st-\u003ever, 0)) {\ndrivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c:175:\t\tkfree_skb_reason(skb, SKB_DROP_REASON_PSP_OUTPUT);\ndrivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c-176-\t\tatomic_inc(\u0026priv-\u003epsp-\u003etx_drop);\n--\ndrivers/net/netdevsim/psp.c=18=nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,\n--\ndrivers/net/netdevsim/psp.c-34-\tif (!skb_transport_header_was_set(skb)) {\ndrivers/net/netdevsim/psp.c:35:\t\trc = SKB_DROP_REASON_PSP_OUTPUT;\ndrivers/net/netdevsim/psp.c-36-\t\tgoto out_unlock;\n--\ndrivers/net/netdevsim/psp.c-40-\tif (!psp_dev_encapsulate(net, skb, pas-\u003etx.spi, pas-\u003eversion, 0)) {\ndrivers/net/netdevsim/psp.c:41:\t\trc = SKB_DROP_REASON_PSP_OUTPUT;\ndrivers/net/netdevsim/psp.c-42-\t\tgoto out_unlock;\n--\ndrivers/net/netdevsim/psp.c-64-\t\tif (psp_dev_rcv(skb, peer_psd-\u003eid, generation, strip_icv)) {\ndrivers/net/netdevsim/psp.c:65:\t\t\trc = SKB_DROP_REASON_PSP_OUTPUT;\ndrivers/net/netdevsim/psp.c-66-\t\t\tgoto out_unlock;\n--\ninclude/net/dropreason-core.h=145=enum skb_drop_reason {\n--\ninclude/net/dropreason-core.h-616-\tSKB_DROP_REASON_PSP_INPUT,\ninclude/net/dropreason-core.h:617:\t/** @SKB_DROP_REASON_PSP_OUTPUT: PSP output checks failed */\ninclude/net/dropreason-core.h:618:\tSKB_DROP_REASON_PSP_OUTPUT,\ninclude/net/dropreason-core.h-619-\t/** @SKB_DROP_REASON_RECURSION_LIMIT: Dead loop on virtual device. */\n--\nnet/psp/psp_sock.c=30=psp_validate_xmit(struct sock *sk, struct net_device *dev, struct sk_buff *skb)\n--\nnet/psp/psp_sock.c-39-\tif (!good) {\nnet/psp/psp_sock.c:40:\t\tsk_skb_reason_drop(sk, skb, SKB_DROP_REASON_PSP_OUTPUT);\nnet/psp/psp_sock.c-41-\t\treturn NULL;\n"
}

25/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 63133
							output: 38
							thoughts: 63
						

Thoughts:
Here's my take on those thoughts:

**Analyzing a Recent Code Addition**

Okay, so I'm looking at this patch and immediately, my brain flags that new `SKB_DROP_REASON_RECURSION_LIMIT` reason. That's fresh, right before this change. To understand the context, my immediate instinct is to check `include/net/dropreason-core.h`, specifically around line 612. I need to see exactly where that drop reason was introduced, what surrounding code it touches, and how it fits into the broader scheme of the drop reason handling. It's all about understanding the relationships here, to ensure this patch plays nicely with the new addition. Gotta get the full picture before I can move on.



26/2 2026/09/13 04:16 tool read-file
0m Args:
{
  "File": "include/net/dropreason-core.h",
  "FirstLine": 610,
  "LineCount": 20
}

Results:
{
  "Contents": " 610:\t\t/**\n 611:\t\t * @SKB_DROP_REASON_PFMEMALLOC: packet allocated from memory reserve\n 612:\t\t * reached a path or socket not eligible for use of memory reserves\n 613:\t\t */\n 614:\t\tSKB_DROP_REASON_PFMEMALLOC,\n 615:\t\t/** @SKB_DROP_REASON_PSP_INPUT: PSP input checks failed */\n 616:\t\tSKB_DROP_REASON_PSP_INPUT,\n 617:\t\t/** @SKB_DROP_REASON_PSP_OUTPUT: PSP output checks failed */\n 618:\t\tSKB_DROP_REASON_PSP_OUTPUT,\n 619:\t\t/** @SKB_DROP_REASON_RECURSION_LIMIT: Dead loop on virtual device. */\n 620:\t\tSKB_DROP_REASON_RECURSION_LIMIT,\n 621:\t\t/**\n 622:\t\t * @SKB_DROP_REASON_TNL_OPT_MISMATCH: the tunnel options\n 623:\t\t * carried by the packet do not match the tunnel configuration, e.g.\n 624:\t\t * a GRE tunnel configured with 'icsum' or 'iseq' received a packet\n 625:\t\t * with no checksum or no sequence number.\n 626:\t\t */\n 627:\t\tSKB_DROP_REASON_TNL_OPT_MISMATCH,\n 628:\t\t/**\n 629:\t\t * @SKB_DROP_REASON_TNL_OLD_SEQ: the sequence number carried\n"
}

27/2 2026/09/13 04:16 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 63798
							output: 123
							thoughts: 14737
						

Thoughts:
**Analysis of the Proposed Patch**

Okay, here's the deal. I've thoroughly examined this patch and it *strictly* falls into the category of changes that don't warrant fuzzing. Let's break down my reasoning, as I've already done an extensive walk-through of the code.

First, the patch's sole purpose is to enhance the existing `kfree_skb` function to include specific "drop reasons" for the `trace_kfree_skb` tracepoint, using `kfree_skb_reason`. The core logic of packet processing in these GRE and tunnel subsystems *remains entirely unchanged*. I've verified this exhaustively. Every single error condition, return value, and control flow path is identical before and after the patch. The patch does not, in any way, alter the essential handling of packets or change the conditions under which a packet is dropped. It’s purely an instrumentation addition.

Second, the patch introduces or modifies functions in several files within the `net/ipv4` and `net/ipv6` directories: `gre_demux.c`, `ip_gre.c`, `ip_tunnel.c`, `ip6_gre.c`, and `ip6_tunnel.c`. These changes, however, are *strictly* limited to setting and passing "drop reason" values to the `kfree_skb_reason` function. The key here is the function `kfree_skb_reason` replaces the call to `kfree_skb`. The only difference between these functions is that `kfree_skb_reason` passes an enum to a tracepoint (which can then be read with a tool like perf).

Third, I've confirmed that the only data structure change is to extend the `enum skb_drop_reason`. This is a *non-functional* change, and it *does not* affect the size, layout, or usage of existing data structures that control packet processing, nor does it affect kernel code size. The new enum value is solely for the *tracepoint* instrumentation.

Fourth, based on the instructions for when we can skip fuzzing, these changes *are* classified under the "non-functional" category. Specifically: "Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints that do not alter control flow or data structures." The patch is *strictly* adding information to the tracepoint. Therefore, by the defined negative criteria, this is not a candidate for fuzzing.



28/2 2026/09/13 04:17 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch series purely annotates existing packet drop points in IPv4/IPv6 GRE and IP tunneling code with specific enum skb_drop_reason values passed to kfree_skb_reason(). This enriches the kfree_skb tracepoint without altering control flow, packet acceptance/rejection decisions, or kernel data structures. As purely tracepoint-related annotation changes that do not modify executable logic or invariants, fuzzing is not warranted.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch series purely annotates existing packet drop points in IPv4/IPv6 GRE and IP tunneling code with specific enum skb_drop_reason values passed to kfree_skb_reason(). This enriches the kfree_skb tracepoint without altering control flow, packet acceptance/rejection decisions, or kernel data structures. As purely tracepoint-related annotation changes that do not modify executable logic or invariants, fuzzing is not warranted.",
  "WorthFuzzing": false
}

29/1 2026/09/13 04:17 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)