Only vxlan reports drop reasons among the tunnel drivers today. The ones
converted here free what they drop with kfree_skb(), which drop_monitor
and the skb:kfree_skb tracepoint do report, but as NOT_SPECIFIED, with
the call site as the only hint at which check failed. That hint does not
go far: all the failures of ip_tunnel_rcv() end at one call site, and so
do nearly all of those of each transmit function. The call site is not a
stable interface either: its offset moves with the compiler, inlining
and the configuration, so a filter on it has to follow every rebuild.
The reason stays the same across kernels, whether NET_DM_ATTR_REASON
reports it or a BPF program matches it by name. The device counters
group the failures coarsely too: rx_errors and tx_errors each lump
together unrelated conditions.
This series covers the generic paths shared by ipip, sit, gre and their
IPv6 counterparts, plus the GRE specific code, in both directions.
A later series will do the same for geneve, bareudp, fou and the
remaining IP in IP drivers.
Patches 1-2 convert the generic receive paths, ip_tunnel_rcv() and
__ip6_tnl_rcv(). Two reasons are added:
TNL_OPT_MISMATCH the options a packet carries do not match the
tunnel configuration
TNL_OLD_SEQ the sequence number is older than the one the
tunnel expects, like TCP_OLD_SEQUENCE for TCP
The second one has a failure mode worth naming: when a peer reboots, its
outgoing sequence number restarts at zero, and the receiver drops
everything until the peer's numbers get past the last one the receiver
accepted. By the counters alone that looks like a misconfiguration: a
packet without the sequence number option bumps the same rx_fifo_errors.
Patches 3-6 convert the GRE specific receive path. gre_parse_header()
returns -EINVAL for every failure, and the only detail its callers could
get was a csum_err flag that none of them read: both ip_gre and ip6_gre
declared it, passed it in and ignored it. gre_parse_header() now returns
a drop reason instead, and its callers take the header length from
tpi->hdr_len. The receive helpers below gre_rcv() return the drop reason
instead of a PACKET_* code, and the PACKET_* codes go away. Three
reasons are added: GRE_INVALID_HDR and GRE_TUNNEL_NOT_FOUND, mirroring
vxlan's VXLAN_INVALID_HDR and VXLAN_VNI_NOT_FOUND, and GRE_CSUM, like
TCP_CSUM and UDP_CSUM.
Patch 4 adds __iptunnel_pull_header_reason(), because
__iptunnel_pull_header() reports a packet too short to pull as -ENOMEM,
the same as an allocation failure, and ip6_gre calls it for every GRE
packet, before the tunnel lookup.
Patches 7-10 convert the transmit side of ip_tunnel, ip_gre, ip6_tunnel
and ip6_gre. One reason is added, TNL_ENCAP, for a failure to build the
encapsulation header. Patch 9 is a small preparation:
prepare_ip6gre_xmit_other() cannot fail, so it is made void rather than
given a drop reason for a branch that never runs. ip6_tnl_xmit() leaves
freeing the packet to its callers, so it and the helpers between it and
the ndo_start_xmit handlers return the drop reason instead of an error.
The transmit side has its own case worth naming: tnl_update_pmtu()
returns -E2BIG after it has already sent the ICMP error back, which is
path MTU discovery working exactly as intended, yet among the device
counters the drop only bumps tx_errors, like a failed encapsulation and
a few other failures do. If the ICMP error never reaches the sender,
the resulting MTU black hole cannot be told from those by the device
counters; the reason tells them apart.
Drop reasons on transmit are not new: vxlan already reports several from
its xmit path, and ip_tunnel_core.c reports RECURSION_LIMIT. They are
most useful for forwarded packets, which is what a tunnel gateway mostly
transmits: the sender is another host, which gets an ICMP error for only
some of these failures, so the drop has to be explained on the gateway.
Changes since v3:
- the functions that took a drop reason output parameter now return the
reason, SKB_NOT_DROPPED_YET on success: gre_parse_header(), the GRE
receive helpers, ip6_tnl_xmit() and the helpers between it and the
ndo_start_xmit handlers (Jakub)
- the callers of gre_parse_header() take the header length from
tpi->hdr_len; the ICMP error handlers pass a new icmp_err argument
instead of a NULL reason pointer
- the IPv6 transmit paths send the ICMP error on PKT_TOO_BIG, and
ipgre_rcv() retries ETH_P_TEB on GRE_TUNNEL_NOT_FOUND: the same
conditions as -EMSGSIZE and PACKET_NEXT before
- the motivation no longer says these drops are invisible; the problem
is the NOT_SPECIFIED reason and the call site all the failures of a
function share (Eric)
- new patch 4, __iptunnel_pull_header_reason(): a packet too short to
pull is reported as PKT_TOO_SMALL instead of NOMEM
- PACKET_RCVD, PACKET_REJECT and PACKET_NEXT are removed
- the ip_tunnel transmit patch no longer says the counters cannot tell
an MTU black hole from a failed route lookup
- the TNL_OPT_MISMATCH kernel-doc also covers an unexpected checksum;
other commit message fixes
- v3: https://lore.kernel.org/netdev/20260916143717.1875082-1-littlesmilingcloud@gmail.com/
- v2: https://lore.kernel.org/netdev/20260913034937.875068-1-littlesmilingcloud@gmail.com/
- v1: https://lore.kernel.org/netdev/20260831215137.549324-1-littlesmilingcloud@gmail.com/
Anton Danilov (10):
ip_tunnel: add drop reasons to the generic RX path
ip6_tunnel: add drop reasons to the generic RX path
gre: make gre_parse_header() report a drop reason
ip_tunnel: add __iptunnel_pull_header_reason()
ip_gre: add drop reasons to the RX path
ip6_gre: add drop reasons to the RX path
ip_tunnel: add drop reasons to the transmit path
ip_gre: add drop reasons to the transmit path
ip6_gre: make prepare_ip6gre_xmit_other() void
ip6_tunnel: add drop reasons to the transmit path
include/net/dropreason-core.h | 39 +++++++
include/net/gre.h | 5 +-
include/net/ip6_tunnel.h | 5 +-
include/net/ip_tunnels.h | 17 ++-
net/ipv4/gre_demux.c | 42 ++++---
net/ipv4/ip_gre.c | 187 +++++++++++++++++++-----------
net/ipv4/ip_tunnel.c | 60 ++++++++--
net/ipv4/ip_tunnel_core.c | 24 ++--
net/ipv6/ip6_gre.c | 211 ++++++++++++++++++++--------------
net/ipv6/ip6_tunnel.c | 123 ++++++++++++--------
10 files changed, 467 insertions(+), 246 deletions(-)
--
2.47.3