Do not store full IPv6 packet in common forwarding case.
authorbluhm <bluhm@openbsd.org>
Sat, 13 Jul 2024 09:34:26 +0000 (09:34 +0000)
committerbluhm <bluhm@openbsd.org>
Sat, 13 Jul 2024 09:34:26 +0000 (09:34 +0000)
commitcf045b768e762ce9ffc97a1dfe52a7bfd3e0f5cc
treeef2e76601e169954964f286e6638fc2d0615dd85
parent0abee971b6b0b08435fe3aa5b23b37e708c5f479
Do not store full IPv6 packet in common forwarding case.

Forwarding IPv6 packets is slower than IPv4.  Reason is that m_copym()
is done for every packet.  Just in case we may have to send an ICMP6
packet, ip6_forward() creates a mbuf copy.  After that mbuf cluster
is read only, so for the ethernet header another mbuf is allocated.
pf NAT and RDR ignores readonly clusters, so it also modifies the
potential ICMP6 packet.
IPv4 ip_forward() avoids all these problems by copying the leading
68 bytes of the original packets onto the stack.  More is not need
for ICMP.  IPv6 RFC 4443 2.4. (c) requires up to 1232 bytes in the
ICMP6 packet.  This cannot be copied to the stack.
The reason for the difference in the standard seems to be that the
ICMP6 packet has to contain the full header chain.  If we have a
simple TCP, UDP or ESP packet without chain, do a shortcut and just
preserve the header for the ICMP6 packet.
Small packets already use stack memory, large packets need extra
mbuf allocation.  Now truncate ICMP6 packet to a reasonable length
if the original packets has a final protocol header directly after
the IPv6 header.  List of suitable protocols contains TCP, UDP, ESP
as they cover the common cases and anything behind the header should
not be needed for path MTU discovery.

OK deraadt@ florian@ mvs@
sys/netinet6/ip6_forward.c