On Tue, Jul 7, 2026 at 6:23 AM Dumitru Ceara <[email protected]> wrote:
>
> On 7/5/26 2:12 AM, Numan Siddique wrote:
> > On Thu, Jul 2, 2026 at 11:27 AM Lorenzo Bianconi
> > <[email protected]> wrote:
> >>
> >>> From: Numan Siddique <[email protected]>
> >>>
> >>> Stateless DNAT in OVN rewrites only the outer IPv4 destination via a
> >>> flow-based 'ip4.dst = <logical_ip>' action.  This is fine for normal
> >>> reply traffic, but it leaves the inner payload of an inbound ICMPv4
> >>> error untouched.  When such an error reaches the downstream logical
> >>> switch pipeline, conntrack tries to correlate the embedded original
> >>> packet with the tracked outgoing flow.  Because that embedded packet
> >>> is the VM's outbound datagram after stateless SNAT, its inner source
> >>> still carries the external (post-NAT) IP, the lookup fails, and the
> >>> packet is marked ct.inv, causing the LS ACL stage to drop it.  The VM
> >>> never sees the ICMP error, kernel PMTU discovery (RFC 1191) breaks,
> >>> and TCP/UDP traffic to destinations beyond a smaller-MTU link
> >>> black-holes.
> >>>
> >>> Emit an additional, higher-priority logical flow for each stateless
> >>> NAT entry that matches the external IP plus any ICMPv4 Destination
> >>> Unreachable error (type 3) and uses the new 'icmp4.inner_ip4.src'
> >>> action to un-NAT the embedded inner source back to the logical IP, in
> >>> addition to rewriting the outer destination.  Every type-3 code quotes
> >>> the original datagram (RFC 792), so this is correct for all of them;
> >>> it covers Fragmentation Needed (code 4, for PMTUD) as well as the
> >>> host/port unreachable codes.  After this rewrite,
> >>> conntrack in the LS zone can correlate the error with the tracked
> >>> outgoing flow, the LS ACL stage allows it, and the VM receives a
> >>> well-formed ICMP error whose inner source is its own private address
> >>> - so the kernel's PMTU update path installs a correct route
> >>> exception.
> >>>
> >>> This behavior is gated by a per-NAT option,
> >>> options:stateless_icmp_helper, on the NB_Global NAT entry.  It
> >>> defaults to true, so the inner-IP rewrite flow is emitted for every
> >>> stateless NAT entry out of the box and PMTUD works without any extra
> >>> configuration.  Operators who do not want the additional flow (for
> >>> example to avoid the pinctrl round-trip for these ICMP errors) can
> >>> opt out by setting options:stateless_icmp_helper=false on the
> >>> individual NAT entry.
> >>>
> >>> The new flow uses priority + 1 so that:
> >>>   - The exempted-ext-ips bypass flow (priority + 2, emits 'next;')
> >>>     still wins for traffic explicitly excluded from NAT.
> >>>   - Non-ICMP traffic falls through to the existing stateless DNAT
> >>>     flow at the original priority.
> >>>
> >>> The rewrite flow round-trips the packet through ovn-controller, so it is
> >>> emitted with the logical router's icmp4-error CoPP meter (when one is
> >>> configured), rate-limiting the punt the same way OVN does for the other
> >>> controller-handled ICMPv4 errors.
> >>>
> >>> Only IPv4 is wired up; IPv6 stateless NAT is not currently supported
> >>> in OVN, so no equivalent action is needed for icmp6 Packet Too Big.
> >>>
> >>> The pinctrl-side implementation of icmp4.inner_ip4.src is in the
> >>> previous patch.
> >>>
> >>> Note that this is required when CMS doesn't use the gateway_mtu
> >>> option and an external PE router generates the ICMPv4 error
> >>> message.
> >>>
> >>> Assisted-by: Claude Opus 4.7, Claude Code
> >>> Signed-off-by: Numan Siddique <[email protected]>
> >>
> >> Acked-by: Lorenzo Bianconi <[email protected]>
> >
> > Thank you Lorenzo.  I applied the series to the main branch.
> >
> > Numan
> >
>
> Hi Numan,
>
> I didn't check too closely but it seems that since this series was
> applied one of our multinode jobs is permafailing:
>
> https://github.com/ovn-org/ovn/actions/workflows/ovn-fake-multinode-tests.yml
>
> 8: ovn multinode stateless NAT - icmp4 PMTUD inner src un-NAT FAILED 
> (multinode.at:1113)
> ...
> ./multinode.at:1102: podman exec ovn-chassis-1 ip netns exec sw0p1 ping -q -c 
> 3 -i 0.3 -w 2 172.20.1.2 | grep "transmitted" | sed 's/time.*ms$/time 0ms/'
> ./multinode.at:1112: podman exec ovn-gw-1 ip netns exec ovn-ext0 ip link set 
> dev ext1 mtu 1100
> ./multinode.at:1113: podman exec ovn-chassis-1 ip netns exec sw0p1 ping -c 20 
> -i 0.5 -s 1300 -M do 172.20.1.2 2>&1 | grep -q "mtu = 1100"
> ./multinode.at:1113: exit code was 1, expected 0
> 8. multinode.at:1044: 8. ovn multinode stateless NAT - icmp4 PMTUD inner src 
> un-NAT (multinode.at:1044): FAILED (multinode.at:1113)
>
> > git log 
> > a19ad49d9a959cd717502beab7fcef46bba05e01..3be2e4cc255865cf9a42a18cc62a5b9ec4411f17
> >  --oneline
> 3be2e4cc25 northd: Extend stateless ICMP helper to more ICMPv4 error types.
> e44e18f46a northd: Emit inner-IP rewrite flow for stateless DNAT.
> ff59f392b4 pinctrl: Implement put_icmp4_inner_ip4_src action.
> 32b4409833 ovn-fields: Add icmp4.inner_ip4.src to rewrite ICMP inner source.
>
> Would you happen to have some time to look into it?

Hi Dumitru,

Oops.

I'll take a look.

Thanks
Numan

>
> Thanks,
> Dumitru
>
>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to