On Sat, Jun 13, 2026 at 8:00 PM <[email protected]> wrote:
>
> Send dev mailing list submissions to
>         [email protected]
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> or, via email, send a message with subject or body 'help' to
>         [email protected]
>
> You can reach the person managing the list at
>         [email protected]
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of dev digest..."
>
>
> Today's Topics:
>
>    1. [PATCH ovn 3/3] northd: Emit inner-IP rewrite flow for
>       stateless DNAT. ([email protected])
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Fri, 12 Jun 2026 19:26:00 -0400
> From: [email protected]
> To: [email protected]
> Subject: [ovs-dev] [PATCH ovn 3/3] northd: Emit inner-IP rewrite flow
>         for stateless DNAT.
> Message-ID: <[email protected]>
>
> 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 ICMPv4 type 3 code 4
> (Fragmentation Needed) 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.  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.
>
> 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.
>

Hi Numan,

Great patch! This nicely fixes the PMTUD issue for stateless DNAT.

Since the inner-IP rewrite infrastructure is now in place, can we also
support Traceroute (ICMPv4 Type 11) for stateless DNAT ?
 It suffers from the exact same conntrack ct.inv drop due to the
un-NATed inner payload.

Do you think we should include Type 11 in this series, or leave it for
a follow-up?

Best regards,
Xie Liu

> Signed-off-by: Numan Siddique <[email protected]>
> Assisted-by: Claude Opus 4.7, Claude Code
> Signed-off-by: Numan Siddique <[email protected]>
> ---
>  Documentation/ref/ovn-logical-flows.7.rst |  29 ++++++
>  NEWS                                      |   7 ++
>  northd/northd.c                           |  33 +++++++
>  ovn-nb.xml                                |  35 +++++++
>  tests/multinode.at                        |  73 ++++++++++++++
>  tests/ovn-northd.at                       |  18 +++-
>  tests/ovn.at                              | 113 +++++++++++++++++++++-
>  7 files changed, 305 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/ref/ovn-logical-flows.7.rst 
> b/Documentation/ref/ovn-logical-flows.7.rst
> index ce4dd53559..45cc2c0d65 100644
> --- a/Documentation/ref/ovn-logical-flows.7.rst
> +++ b/Documentation/ref/ovn-logical-flows.7.rst
> @@ -2775,6 +2775,22 @@ flows do not get programmed for load balancers with 
> IPv6 *VIPs*.
>    rule is of type dnat_and_snat and has ``stateless=true`` in the options, 
> then
>    the action would be ``ip4/6.dst=(B)``.
>
> +  For an IPv4 stateless ``dnat_and_snat`` rule that has
> +  ``options:stateless_icmp_helper`` set to ``true`` (the default), an
> +  additional flow at priority *P + 1* is added that matches ``ip && ip4.dst
> +  == A && icmp4 && icmp4.type == 3 && icmp4.code == 4`` with the action
> +  ``ip4.dst = B; icmp4.inner_ip4.src = B; next;``, where *P* is the priority 
> of
> +  the flow above. This rewrites the outer destination and un-NATs the source
> +  embedded in the inbound ICMPv4 ``Fragmentation Needed`` error payload (from
> +  the external IP *A* back to the logical IP *B*), so that conntrack in the
> +  downstream logical switch can correlate the error with the tracked outgoing
> +  flow and Path MTU discovery (RFC 1191) works end-to-end across stateless
> +  NAT. See ``options:stateless_icmp_helper`` in the ``NAT`` table of the
> +  ``OVN_Northbound`` database (``ovn-nb`` (5)). The priority is *P + 1* so 
> that
> +  the ``exempted_ext_ips`` bypass flow (at *P + 2*) still wins for traffic
> +  excluded from NAT, and non-ICMP traffic falls through to the regular
> +  stateless DNAT flow.
> +
>    If the NAT rule has ``allowed_ext_ips`` configured, then there is an
>    additional match ``ip4.src == allowed_ext_ips``. Similarly, for IPV6, match
>    would be ``ip6.src == allowed_ext_ips``.
> @@ -2815,6 +2831,19 @@ the egress pipeline.
>    the IPv6 case. If the NAT rule is of type dnat_and_snat and has
>    ``stateless=true`` in the options, then the action would be 
> ``ip4/6.dst=(B)``.
>
> +  For an IPv4 stateless ``dnat_and_snat`` rule that has
> +  ``options:stateless_icmp_helper`` set to ``true`` (the default), an
> +  additional priority-101 flow is added that matches ``ip && ip4.dst == B &&
> +  inport == GW && icmp4 && icmp4.type == 3 && icmp4.code == 4`` with the 
> action
> +  ``ip4.dst = B; icmp4.inner_ip4.src = B; next;``. This rewrites the outer
> +  destination and un-NATs the source embedded in the inbound ICMPv4
> +  ``Fragmentation Needed`` error payload (back to the logical IP *B*), so 
> that
> +  conntrack in the downstream logical switch can correlate the error with the
> +  tracked outgoing flow and Path MTU discovery (RFC 1191) works end-to-end
> +  across stateless NAT. See
> +  ``options:stateless_icmp_helper`` in the ``NAT`` table of the
> +  ``OVN_Northbound`` database (``ovn-nb`` (5)).
> +
>    If the NAT rule cannot be handled in a distributed manner, then the
>    priority-100 flow above is only programmed on the gateway chassis.
>
> diff --git a/NEWS b/NEWS
> index 748ae30eb2..216728998f 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -33,6 +33,13 @@ Post v26.03.0
>       The DHCP and unbound-router ARP/ND drop lflows for external
>       ports were updated to key on the external LSP's inport
>       accordingly.
> +   - Added a new "icmp4.inner_ip4.src" action that rewrites the source
> +     IPv4 address embedded in an ICMPv4 error's inner packet.  ovn-northd
> +     uses it for stateless "dnat_and_snat" rules, controlled by the new
> +     "options:stateless_icmp_helper" NAT option (default true), so that
> +     inbound ICMPv4 "fragmentation needed" errors generated by an external
> +     router are un-NATed correctly and Path MTU discovery works through
> +     stateless NAT.
>
>  OVN v26.03.0 - xxx xx xxxx
>  --------------------------
> diff --git a/northd/northd.c b/northd/northd.c
> index 0dbf174269..369322c2ac 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -17654,6 +17654,39 @@ build_lrouter_in_dnat_flow(struct lflow_table 
> *lflows,
>
>      ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, priority, ds_cstr(match),
>                    ds_cstr(actions), lflow_ref, WITH_HINT(&nat->header_));
> +
> +    /* For stateless DNAT, the action above only rewrites the outer IPv4
> +     * destination.  An inbound ICMPv4 error (RFC 792 / RFC 1191) carries
> +     * the original (post-NAT) packet inside its payload, whose source is
> +     * the external (post-SNAT) IP.  The conntrack-based ACL check in the
> +     * downstream logical switch zone uses that inner tuple to match the
> +     * reverse direction of the tracked outgoing flow; without un-NATing
> +     * the inner ip4.src back to the logical IP, that lookup fails and the
> +     * error is dropped as ct.inv.
> +     *
> +     * Emit a higher-priority flow that matches the same external IP plus
> +     * ICMPv4 type 3 code 4 (Fragmentation Needed and DF set) and rewrites
> +     * the outer ip4.dst and the embedded inner ip4.src to the logical IP,
> +     * so PMTUD works end-to-end through stateless NAT. */
> +    if (stateless && !is_v6 &&
> +        smap_get_bool(&nat_entry->nb->options, "stateless_icmp_helper",
> +                      true)) {
> +        size_t match_len = match->length;
> +
> +        ds_put_cstr(match,
> +                    " && icmp4 && icmp4.type == 3 && icmp4.code == 4");
> +
> +        ds_clear(actions);
> +        ds_put_format(actions,
> +                      "ip4.dst=%s; icmp4.inner_ip4.src = %s; next;",
> +                      nat->logical_ip, nat->logical_ip);
> +
> +        ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, priority + 1,
> +                      ds_cstr(match), ds_cstr(actions), lflow_ref,
> +                      WITH_HINT(&nat->header_));
> +
> +        ds_truncate(match, match_len);
> +    }
>  }
>
>  static void
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 15fb1d7e86..769bf05e4f 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -5457,6 +5457,41 @@ or
>        tracking state or not.
>      </column>
>
> +    <column name="options" key="stateless_icmp_helper"
> +            type='{"type": "boolean"}'>
> +      <p>
> +        Applies only to stateless <code>dnat_and_snat</code> rules (that
> +        is, NATs with <ref column="options" key="stateless"/> set to
> +        <code>true</code>) on IPv4 addresses. Defaults to
> +        <code>true</code>.
> +      </p>
> +
> +      <p>
> +        A stateless DNAT rule rewrites only the outer IPv4 destination of
> +        inbound packets. For an inbound ICMPv4 error (for example a
> +        <code>Fragmentation Needed</code> message generated for Path MTU
> +        discovery, RFC 1191), the original packet embedded in the ICMP
> +        payload still carries the external, post-NAT IP as its source.
> +        When the error reaches the downstream logical switch, conntrack
> +        cannot correlate the embedded tuple with the tracked outgoing
> +        flow, the packet is marked <code>ct.inv</code> and dropped by the
> +        ACL stage, and PMTU discovery breaks.
> +      </p>
> +
> +      <p>
> +        When this option is <code>true</code>, <code>ovn-northd</code>
> +        emits an additional, higher-priority logical flow in the router
> +        ingress DNAT stage that matches ICMPv4 type 3 code 4 errors
> +        destined to the external IP. It rewrites the outer IPv4
> +        destination to the logical IP and, using the
> +        <code>icmp4.inner_ip4.src</code> action, un-NATs the embedded
> +        inner IPv4 source from the external IP back to the logical IP, so
> +        that conntrack can correlate the error and PMTU discovery works
> +        end-to-end. Set it to <code>false</code> to suppress this flow for
> +        an individual NAT entry.
> +      </p>
> +    </column>
> +
>      <column name="options" key="add_route">
>        If set to <code>true</code>, then neighbor routers will have logical
>        flows added that will allow for routing to the NAT address. It also 
> will
> diff --git a/tests/multinode.at b/tests/multinode.at
> index 069f2a677d..37ef523f95 100644
> --- a/tests/multinode.at
> +++ b/tests/multinode.at
> @@ -1041,6 +1041,79 @@ run_ns_traffic
>  AT_CLEANUP
>  ])
>
> +AT_SETUP([ovn multinode stateless NAT - icmp4 PMTUD inner src un-NAT])
> +
> +# Check that ovn-fake-multinode setup is up and running
> +check_fake_multinode_setup
> +
> +# Delete the multinode NB and OVS resources before starting the test.
> +cleanup_multinode_resources
> +
> +m_as ovn-chassis-1 ip link del sw0p1-p
> +
> +# Reset geneve tunnels
> +for c in ovn-chassis-1 ovn-gw-1
> +do
> +    m_as $c ovs-vsctl set open . external-ids:ovn-encap-type=geneve
> +done
> +
> +OVS_WAIT_UNTIL([m_as ovn-chassis-1 ip link show | grep -q genev_sys])
> +OVS_WAIT_UNTIL([m_as ovn-gw-1 ip link show | grep -q genev_sys])
> +
> +# Internal switch with one VM (10.0.0.3) on ovn-chassis-1.
> +check multinode_nbctl ls-add sw0
> +check multinode_nbctl lsp-add sw0 sw0-port1
> +check multinode_nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:03 
> 10.0.0.3"
> +
> +m_as ovn-chassis-1 /data/create_fake_vm.sh sw0-port1 sw0p1 50:54:00:00:00:03 
> 1342 10.0.0.3 24 10.0.0.1
> +
> +# Gateway router pinned to ovn-gw-1.
> +check multinode_nbctl lr-add lr0 -- set Logical_Router lr0 
> options:chassis=ovn-gw-1
> +check multinode_nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
> +check multinode_nbctl lsp-add-router-port sw0 sw0-lr0 lr0-sw0
> +
> +# External / provider network.
> +check multinode_nbctl ls-add public
> +check multinode_nbctl lsp-add-localnet-port public ln-public public
> +check multinode_nbctl lrp-add lr0 lr0-public 00:11:22:00:ff:01 
> 172.20.0.100/24
> +check multinode_nbctl lsp-add-router-port public public-lr0 lr0-public
> +check multinode_nbctl lr-route-add lr0 0.0.0.0/0 172.20.0.1
> +
> +# Stateless dnat_and_snat for the VM.  options:stateless_icmp_helper defaults
> +# to true, so ovn-northd emits the extra DNAT flow that, for an inbound 
> ICMPv4
> +# "fragmentation needed" error destined to 172.20.0.110, un-NATs the inner
> +# source from 172.20.0.110 back to 10.0.0.3 (icmp4.inner_ip4.src).  Unlike
> +# stateful NAT (where conntrack fixes the embedded header automatically),
> +# stateless NAT relies entirely on this flow for PMTUD to work.
> +check multinode_nbctl --stateless lr-nat-add lr0 dnat_and_snat 172.20.0.110 
> 10.0.0.3
> +
> +m_as ovn-gw-1 ovs-vsctl set open . 
> external-ids:ovn-bridge-mappings=public:br-ex
> +m_as ovn-chassis-1 ovs-vsctl set open . 
> external-ids:ovn-bridge-mappings=public:br-ex
> +
> +m_wait_for_ports_up
> +
> +# ovn-ext0 routes between the OVN public net (172.20.0.0/24) and a downstream
> +# net (172.20.1.0/24); ovn-ext2 (172.20.1.2) is the far host behind it.
> +m_add_internal_port ovn-gw-1 ovn-ext0 br-ex ext0 172.20.0.1/24
> +m_add_internal_port ovn-gw-1 ovn-ext0 br-ex ext1 172.20.1.1/24
> +m_add_internal_port ovn-gw-1 ovn-ext2 br-ex ext2 172.20.1.2/24 172.20.1.1
> +
> +# Baseline: the VM reaches the far host through stateless NAT.
> +M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3 -i 0.3 -w 2 
> 172.20.1.2 | FORMAT_PING], \
> +[0], [dnl
> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
> +])
> +
> +# Shrink the downstream link MTU so ovn-ext0 emits ICMPv4 "fragmentation
> +# needed" (type 3, code 4) towards 172.20.0.110 (the VM's stateless SNAT
> +# address) for oversized DF traffic.  The error's inner packet carries
> +# 172.20.0.110 as its source; the VM only honors the PMTU signal if OVN
> +# un-NATs that inner source back to 10.0.0.3.
> +M_NS_CHECK_EXEC([ovn-gw-1], [ovn-ext0], [ip link set dev ext1 mtu 1100])
> +M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -c 20 -i 0.5 -s 1300 -M do 
> 172.20.1.2 2>&1 | grep -q "mtu = 1100"])
> +
> +AT_CLEANUP
> +
>  PMTUD_SWITCH_TESTS(["geneve"])
>  PMTUD_SWITCH_TESTS(["vxlan"])
>
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index f87b14c9a1..9b875f5adc 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -1087,13 +1087,29 @@ check ovn-nbctl lr-nat-del R1 dnat_and_snat  
> 172.16.1.1
>  echo
>  echo "IPv4: stateless"
>  check ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat  
> 172.16.1.1 50.0.0.11
> +dnl Two ip4.dst= flows: the regular stateless DNAT flow plus the default
> +dnl stateless_icmp_helper flow that also rewrites the inner ICMPv4 src.
> +check_flow_match_sets 2 0 0 2 1 0 0
> +dnl stateless_icmp_helper defaults to true, so the inner-IP rewrite flow
> +dnl is present.
> +check_flow_matches "icmp4.inner_ip4.src" 1
> +check ovn-nbctl lr-nat-del R1 dnat_and_snat  172.16.1.1
> +
> +echo
> +echo "IPv4: stateless, stateless_icmp_helper=false"
> +check ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat  
> 172.16.1.1 50.0.0.11
> +check ovn-nbctl --wait=sb set NAT . options:stateless_icmp_helper=false
> +dnl With the helper disabled, only the regular stateless DNAT flow remains
> +dnl and the inner-IP rewrite flow is gone.
>  check_flow_match_sets 2 0 0 1 1 0 0
> +check_flow_matches "icmp4.inner_ip4.src" 0
>  check ovn-nbctl lr-nat-del R1 dnat_and_snat  172.16.1.1
>
>  echo
>  echo "IPv4: stateless with match"
>  check ovn-nbctl --wait=sb --match="udp" --stateless lr-nat-add R1 
> dnat_and_snat  172.16.1.1 50.0.0.11
> -check_flow_match_sets 2 0 0 1 1 0 0
> +dnl As above, the stateless_icmp_helper flow adds a second ip4.dst= flow.
> +check_flow_match_sets 2 0 0 2 1 0 0
>  check ovn-nbctl lr-nat-del R1 dnat_and_snat  172.16.1.1
>
>  echo
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 68061a623d..dddbebb0e4 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -22705,6 +22705,113 @@ OVN_CLEANUP([hv1])
>  AT_CLEANUP
>  ])
>
> +AT_SETUP([stateless NAT - icmp4.inner_ip4.src rewrite])
> +AT_KEYWORDS([stateless-nat icmp4-inner-ip4-src])
> +AT_SKIP_IF([test $HAVE_SCAPY = no])
> +ovn_start
> +
> +# Topology:
> +#   "external" host (ext1, on the public LS) --- lr0 (gw router) --- vm1 (on 
> sw0)
> +#
> +# lr0 has a stateless dnat_and_snat rule that maps the external IP
> +# 172.168.0.110 to the logical IP 10.0.0.3 (vm1).  With
> +# options:stateless_icmp_helper defaulting to true, ovn-northd emits a
> +# higher-priority DNAT flow that matches inbound ICMPv4 "Fragmentation
> +# Needed" errors (type 3, code 4) destined to the external IP and applies
> +# the action "ip4.dst = 10.0.0.3; icmp4.inner_ip4.src = 10.0.0.3;".
> +#
> +# An inbound ICMP error quotes the VM's original outbound (post-SNAT)
> +# datagram, so its inner source is the external IP 172.168.0.110.  This test
> +# injects such an error from the external side and verifies that
> +# ovn-controller (pinctrl) DNATs the outer destination to 10.0.0.3 and
> +# un-NATs the inner (embedded) IPv4 source back to 10.0.0.3 - while leaving
> +# the inner destination untouched - before delivering the packet to vm1.
> +
> +vm1_mac=50:54:00:00:00:01
> +vm1_ip=10.0.0.3
> +rtr_int_mac=00:00:00:00:ff:01
> +rtr_ext_mac=00:00:20:20:12:13
> +ext1_mac=00:00:00:00:00:99
> +ext1_ip=172.168.0.50
> +nat_ext_ip=172.168.0.110
> +
> +# Internal switch with vm1.
> +check ovn-nbctl ls-add sw0
> +check ovn-nbctl lsp-add sw0 sw0-vm1
> +check ovn-nbctl lsp-set-addresses sw0-vm1 "$vm1_mac $vm1_ip"
> +
> +# Router (gateway router pinned to hv1).
> +check ovn-nbctl lr-add lr0
> +check ovn-nbctl lrp-add lr0 lr0-sw0 $rtr_int_mac 10.0.0.1/24
> +check ovn-nbctl lsp-add-router-port sw0 sw0-lr0 lr0-sw0
> +
> +# Public switch with the external host.
> +check ovn-nbctl ls-add public
> +check ovn-nbctl lrp-add lr0 lr0-public $rtr_ext_mac 172.168.0.100/24
> +check ovn-nbctl lsp-add-router-port public public-lr0 lr0-public
> +check ovn-nbctl lsp-add public ext1
> +check ovn-nbctl lsp-set-addresses ext1 "$ext1_mac $ext1_ip"
> +
> +check ovn-nbctl set logical_router lr0 options:chassis=hv1
> +
> +# Stateless dnat_and_snat: external 172.168.0.110 <-> logical 10.0.0.3.
> +check ovn-nbctl --wait=sb --stateless lr-nat-add lr0 dnat_and_snat \
> +    $nat_ext_ip $vm1_ip
> +
> +net_add n1
> +sim_add hv1
> +as hv1
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.1
> +ovs-vsctl -- add-port br-int hv1-vif1 -- \
> +    set interface hv1-vif1 external-ids:iface-id=sw0-vm1 \
> +    options:tx_pcap=hv1/vif1-tx.pcap \
> +    options:rxq_pcap=hv1/vif1-rx.pcap \
> +    ofport-request=1
> +ovs-vsctl -- add-port br-int hv1-vif2 -- \
> +    set interface hv1-vif2 external-ids:iface-id=ext1 \
> +    options:tx_pcap=hv1/vif2-tx.pcap \
> +    options:rxq_pcap=hv1/vif2-rx.pcap \
> +    ofport-request=2
> +
> +wait_for_ports_up
> +check ovn-nbctl --wait=hv sync
> +
> +# The inner packet is the original (post-SNAT) datagram quoted in the ICMP
> +# error.  Use a raw 8-byte blob for the embedded L4 header so that no inner
> +# L4 checksum (which the action does not recompute) is involved.
> +inner_l4="0102030405060708"
> +
> +# ICMP fragmentation-needed error from ext1 to the NAT external IP.  The
> +# embedded original packet is the VM's outbound datagram after stateless
> +# SNAT, so its inner source is the external IP and its inner destination is
> +# some far host (50.0.0.100).
> +packet=$(fmt_pkt "Ether(dst='$rtr_ext_mac', src='$ext1_mac')/ \
> +                  IP(src='$ext1_ip', dst='$nat_ext_ip', ttl=64)/ \
> +                  ICMP(type=3, code=4, nexthopmtu=1400)/ \
> +                  IP(src='$nat_ext_ip', dst='50.0.0.100', ttl=63, proto=17)/ 
> \
> +                  bytes.fromhex('$inner_l4')")
> +
> +# Expected packet delivered to vm1: the router has DNATed the outer
> +# destination to 10.0.0.3, decremented the outer TTL, rewritten the L2
> +# addresses, and (via pinctrl) un-NATed the inner IPv4 source to 10.0.0.3.
> +# The inner destination (50.0.0.100) is left unchanged.
> +expected=$(fmt_pkt "Ether(dst='$vm1_mac', src='$rtr_int_mac')/ \
> +                    IP(src='$ext1_ip', dst='$vm1_ip', ttl=63)/ \
> +                    ICMP(type=3, code=4, nexthopmtu=1400)/ \
> +                    IP(src='$vm1_ip', dst='50.0.0.100', ttl=63, proto=17)/ \
> +                    bytes.fromhex('$inner_l4')")
> +echo $expected > vif1.expected
> +
> +as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> +
> +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
> +
> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
> +
> +OVN_CLEANUP([hv1])
> +AT_CLEANUP
> +
>  OVN_FOR_EACH_NORTHD([
>  AT_SETUP([IP packet buffering])
>  AT_KEYWORDS([ip-buffering])
> @@ -26932,14 +27039,16 @@ test_ip vif11 f00000000011 000001010203 $sip $dip 
> vif-north
>  # Confirm that South to North traffic works fine.
>  OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv4/vif-north-tx.pcap], 
> [vif-north.expected])
>
> -# Confirm that NATing happened without connection tracker
> +# Confirm that NATing happened without connection tracker.
> +# Two ip4.dst= flows are expected: the regular stateless DNAT flow plus the
> +# default stateless_icmp_helper flow (which also carries 
> icmp4.inner_ip4.src).
>  ovn-sbctl dump-flows router > sbflows
>  AT_CAPTURE_FILE([sbflows])
>  AT_CHECK([for regex in ct_snat ct_dnat ip4.dst= ip4.src=; do
>    grep -c "$regex" sbflows;
>  done], [0], [0
>  0
> -1
> +2
>  1
>  ])
>
> --
> 2.54.0
>
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
> ------------------------------
>
> End of dev Digest, Vol 203, Issue 172
> *************************************
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to