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?

Thanks,
Dumitru



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

Reply via email to