* [PATCH net-next v5] net: dropreason: add SKB_DROP_REASON_IP_TTL_EXCEEDED
@ 2026-09-10 9:49 Junjie Cao
2026-09-11 2:49 ` Hangbin Liu
2026-09-12 0:00 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Junjie Cao @ 2026-09-10 9:49 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: David Ahern, Simon Horman, Ido Schimmel,
Fernando Fernandez Mancera, Jiayuan Chen, Hangbin Liu, netdev,
linux-kernel
The forwarding paths report an expired TTL or hop limit as
SKB_DROP_REASON_IP_INHDR, the reason otherwise used for a header that is
malformed (ip_input.c, exthdrs.c, br_netfilter). Nothing else in the drop
path separates the two: IPSTATS_MIB_INHDRERRORS covers both, and the TTL
check runs before NF_INET_FORWARD, so netfilter tracing stops at
PREROUTING and never sees the drop.
The Fedora bug linked below shows how that reads in practice. The
reporter took kfree_skb(reason=IP_INHDR, loc=ip_forward) to mean the
software header checksum check had failed, and worked through RX checksum
offload, tc csum actions and both libvirt firewall backends before the
drops turned out to be replies arriving with TTL 1. ip_forward() never
verifies the header checksum; that runs earlier, in ip_rcv_core(), and
reports IP_CSUM.
TTL expiry is not a corner case -- every traceroute through a Linux
router goes through too_many_hops.
The three loopback hop limit checks in exthdrs.c drop with no reason at
all; give them the new one.
IPSTATS_MIB_INHDRERRORS stays as it is: RFC 1213 counts time-to-live
exceeded under ipInHdrErrors. The drop reason has no such constraint.
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2517131
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
---
v5: move the entry next to the other IP_* reasons, after IP_INVALID_DEST
(Jakub Kicinski)
IPVS decrement_ttl() is a follow-up: its xmit callers free at tx_error
with plain kfree_skb(), so the reason has to come back out of
__ip_vs_get_out_rt() (David Ahern, Hangbin Liu)
v4: https://lore.kernel.org/netdev/20260907030133.482834-1-junjie.cao@intel.com/
v3: https://lore.kernel.org/netdev/20260904030112.450920-1-junjie.cao@intel.com/
v2: https://lore.kernel.org/netdev/20260901020613.417495-1-junjie.cao@intel.com/
v1: https://lore.kernel.org/netdev/20260825073906.336072-1-junjie.cao@intel.com/
include/net/dropreason-core.h | 6 ++++++
net/ipv4/ip_forward.c | 2 +-
net/ipv6/exthdrs.c | 6 +++---
net/ipv6/ip6_output.c | 2 +-
4 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index 2f312d1f67d6..12f909651591 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -93,6 +93,7 @@
FN(IP_INVALID_SOURCE) \
FN(IP_LOCALNET) \
FN(IP_INVALID_DEST) \
+ FN(IP_TTL_EXCEEDED) \
FN(PKT_TOO_BIG) \
FN(DUP_FRAG) \
FN(FRAG_REASM_TIMEOUT) \
@@ -474,6 +475,11 @@ enum skb_drop_reason {
* 1) dest ip is 0
*/
SKB_DROP_REASON_IP_INVALID_DEST,
+ /**
+ * @SKB_DROP_REASON_IP_TTL_EXCEEDED: IPv4 TTL or IPv6 hop limit <= 1
+ * (see IPSTATS_MIB_INHDRERRORS)
+ */
+ SKB_DROP_REASON_IP_TTL_EXCEEDED,
/**
* @SKB_DROP_REASON_PKT_TOO_BIG: packet size is too big (maybe exceed the
* MTU)
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 8b65f12583eb..b242561d37e7 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -174,7 +174,7 @@ int ip_forward(struct sk_buff *skb)
/* Tell the sender its packet died... */
__IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
- SKB_DR_SET(reason, IP_INHDR);
+ SKB_DR_SET(reason, IP_TTL_EXCEEDED);
drop:
kfree_skb_reason(skb, reason);
return NET_RX_DROP;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 09a4552f7f08..55391e2e5612 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -464,7 +464,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
ICMPV6_EXC_HOPLIMIT, 0);
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
return -1;
}
ipv6_hdr(skb)->hop_limit--;
@@ -623,7 +623,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
ICMPV6_EXC_HOPLIMIT, 0);
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
return -1;
}
ipv6_hdr(skb)->hop_limit--;
@@ -815,7 +815,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
0);
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
return -1;
}
ipv6_hdr(skb)->hop_limit--;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 96ee3de55f93..ddaba0aebcb1 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -577,7 +577,7 @@ int ip6_forward(struct sk_buff *skb)
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
- kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR);
+ kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
return -ETIMEDOUT;
}
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net-next v5] net: dropreason: add SKB_DROP_REASON_IP_TTL_EXCEEDED
2026-09-10 9:49 [PATCH net-next v5] net: dropreason: add SKB_DROP_REASON_IP_TTL_EXCEEDED Junjie Cao
@ 2026-09-11 2:49 ` Hangbin Liu
2026-09-12 0:00 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Hangbin Liu @ 2026-09-11 2:49 UTC (permalink / raw)
To: Junjie Cao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
David Ahern, Simon Horman, Ido Schimmel,
Fernando Fernandez Mancera, Jiayuan Chen, netdev, linux-kernel
On Thu, Sep 10, 2026 at 05:49:37PM +0800, Junjie Cao wrote:
> The forwarding paths report an expired TTL or hop limit as
> SKB_DROP_REASON_IP_INHDR, the reason otherwise used for a header that is
> malformed (ip_input.c, exthdrs.c, br_netfilter). Nothing else in the drop
> path separates the two: IPSTATS_MIB_INHDRERRORS covers both, and the TTL
> check runs before NF_INET_FORWARD, so netfilter tracing stops at
> PREROUTING and never sees the drop.
>
> The Fedora bug linked below shows how that reads in practice. The
> reporter took kfree_skb(reason=IP_INHDR, loc=ip_forward) to mean the
> software header checksum check had failed, and worked through RX checksum
> offload, tc csum actions and both libvirt firewall backends before the
> drops turned out to be replies arriving with TTL 1. ip_forward() never
> verifies the header checksum; that runs earlier, in ip_rcv_core(), and
> reports IP_CSUM.
>
> TTL expiry is not a corner case -- every traceroute through a Linux
> router goes through too_many_hops.
>
> The three loopback hop limit checks in exthdrs.c drop with no reason at
> all; give them the new one.
>
> IPSTATS_MIB_INHDRERRORS stays as it is: RFC 1213 counts time-to-live
> exceeded under ipInHdrErrors. The drop reason has no such constraint.
>
> Link: https://bugzilla.redhat.com/show_bug.cgi?id=2517131
> Signed-off-by: Junjie Cao <junjie.cao@intel.com>
> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
> Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
> ---
> v5: move the entry next to the other IP_* reasons, after IP_INVALID_DEST
> (Jakub Kicinski)
> IPVS decrement_ttl() is a follow-up: its xmit callers free at tx_error
> with plain kfree_skb(), so the reason has to come back out of
> __ip_vs_get_out_rt() (David Ahern, Hangbin Liu)
> v4: https://lore.kernel.org/netdev/20260907030133.482834-1-junjie.cao@intel.com/
> v3: https://lore.kernel.org/netdev/20260904030112.450920-1-junjie.cao@intel.com/
> v2: https://lore.kernel.org/netdev/20260901020613.417495-1-junjie.cao@intel.com/
> v1: https://lore.kernel.org/netdev/20260825073906.336072-1-junjie.cao@intel.com/
> include/net/dropreason-core.h | 6 ++++++
> net/ipv4/ip_forward.c | 2 +-
> net/ipv6/exthdrs.c | 6 +++---
> net/ipv6/ip6_output.c | 2 +-
> 4 files changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
> index 2f312d1f67d6..12f909651591 100644
> --- a/include/net/dropreason-core.h
> +++ b/include/net/dropreason-core.h
> @@ -93,6 +93,7 @@
> FN(IP_INVALID_SOURCE) \
> FN(IP_LOCALNET) \
> FN(IP_INVALID_DEST) \
> + FN(IP_TTL_EXCEEDED) \
> FN(PKT_TOO_BIG) \
> FN(DUP_FRAG) \
> FN(FRAG_REASM_TIMEOUT) \
> @@ -474,6 +475,11 @@ enum skb_drop_reason {
> * 1) dest ip is 0
> */
> SKB_DROP_REASON_IP_INVALID_DEST,
> + /**
> + * @SKB_DROP_REASON_IP_TTL_EXCEEDED: IPv4 TTL or IPv6 hop limit <= 1
> + * (see IPSTATS_MIB_INHDRERRORS)
> + */
> + SKB_DROP_REASON_IP_TTL_EXCEEDED,
> /**
> * @SKB_DROP_REASON_PKT_TOO_BIG: packet size is too big (maybe exceed the
> * MTU)
> diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
> index 8b65f12583eb..b242561d37e7 100644
> --- a/net/ipv4/ip_forward.c
> +++ b/net/ipv4/ip_forward.c
> @@ -174,7 +174,7 @@ int ip_forward(struct sk_buff *skb)
> /* Tell the sender its packet died... */
> __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
> icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
> - SKB_DR_SET(reason, IP_INHDR);
> + SKB_DR_SET(reason, IP_TTL_EXCEEDED);
> drop:
> kfree_skb_reason(skb, reason);
> return NET_RX_DROP;
> diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
> index 09a4552f7f08..55391e2e5612 100644
> --- a/net/ipv6/exthdrs.c
> +++ b/net/ipv6/exthdrs.c
> @@ -464,7 +464,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
> __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
> icmpv6_send(skb, ICMPV6_TIME_EXCEED,
> ICMPV6_EXC_HOPLIMIT, 0);
> - kfree_skb(skb);
> + kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
> return -1;
> }
> ipv6_hdr(skb)->hop_limit--;
> @@ -623,7 +623,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev)
> __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
> icmpv6_send(skb, ICMPV6_TIME_EXCEED,
> ICMPV6_EXC_HOPLIMIT, 0);
> - kfree_skb(skb);
> + kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
> return -1;
> }
> ipv6_hdr(skb)->hop_limit--;
> @@ -815,7 +815,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
> __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
> icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
> 0);
> - kfree_skb(skb);
> + kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
> return -1;
> }
> ipv6_hdr(skb)->hop_limit--;
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 96ee3de55f93..ddaba0aebcb1 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -577,7 +577,7 @@ int ip6_forward(struct sk_buff *skb)
> icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
> __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
>
> - kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR);
> + kfree_skb_reason(skb, SKB_DROP_REASON_IP_TTL_EXCEEDED);
> return -ETIMEDOUT;
> }
>
> --
> 2.43.0
>
Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net-next v5] net: dropreason: add SKB_DROP_REASON_IP_TTL_EXCEEDED
2026-09-10 9:49 [PATCH net-next v5] net: dropreason: add SKB_DROP_REASON_IP_TTL_EXCEEDED Junjie Cao
2026-09-11 2:49 ` Hangbin Liu
@ 2026-09-12 0:00 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-12 0:00 UTC (permalink / raw)
To: Junjie Cao
Cc: davem, edumazet, kuba, pabeni, dsahern, horms, idosch, fmancera,
jiayuan.chen, hangbin.liu, netdev, linux-kernel
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 10 Sep 2026 17:49:37 +0800 you wrote:
> The forwarding paths report an expired TTL or hop limit as
> SKB_DROP_REASON_IP_INHDR, the reason otherwise used for a header that is
> malformed (ip_input.c, exthdrs.c, br_netfilter). Nothing else in the drop
> path separates the two: IPSTATS_MIB_INHDRERRORS covers both, and the TTL
> check runs before NF_INET_FORWARD, so netfilter tracing stops at
> PREROUTING and never sees the drop.
>
> [...]
Here is the summary with links:
- [net-next,v5] net: dropreason: add SKB_DROP_REASON_IP_TTL_EXCEEDED
https://git.kernel.org/netdev/net-next/c/219c6b768ec7
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-12 0:01 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-10 9:49 [PATCH net-next v5] net: dropreason: add SKB_DROP_REASON_IP_TTL_EXCEEDED Junjie Cao
2026-09-11 2:49 ` Hangbin Liu
2026-09-12 0:00 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®