diff mbox series

[ovs-dev] northd: Allow need frag to be SNATed

Message ID 20230920062150.13458-1-amusil@redhat.com
State Accepted
Delegated to: Dumitru Ceara
Headers show
Series [ovs-dev] northd: Allow need frag to be SNATed | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes fail github build: failed

Commit Message

Ales Musil Sept. 20, 2023, 6:21 a.m. UTC
Considering following topology:
client - sw0 - lrp0 - lr - lrp1 - sw1 - server
sw0 in subnet 192.168.0.0/24
sw1 in subnet 172.168.0.0/24
SNAT configured for sw0 subnet
gateway_mtu=1400 configured for lrp0

If we send UDP traffic from client to server
and server responds with packet bigger than 1400
the following sequence will happen:

1) Packet is coming into lr via lrp1
2) unSNAT
3) Routing, the outport will be set to lrp1
4) Check for packet larger will fail
5) We will generate ICMP need frag

However, the last step is wrong from the server
perspective. The ICMP message will have IP source
address = lrp1 IP address. Which means that SNAT won't
happen because the source is not within the sw0 subnet,
but the inner packet has sw0 subnet address, because it
was unSNATted. This results in server ignoring the ICMP
message because server never sent any packet to the
sw0 subnet.

To fix this issue use outport IP address as source instead
of the inport one for the ICMP error message. This will
lead to SNAT for the packet which will result in correct
addresses on the sw1 side.

Reported-at: https://issues.redhat.com/browse/FDP-39
Signed-off-by: Ales Musil <amusil@redhat.com>
---
 northd/northd.c          |  30 +++++---
 tests/ovn-northd.at      |  65 ++++++++---------
 tests/ovn.at             |   6 +-
 tests/system-ovn-kmod.at | 152 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 210 insertions(+), 43 deletions(-)

Comments

Ales Musil Sept. 20, 2023, 7:37 a.m. UTC | #1
On Wed, Sep 20, 2023 at 8:21 AM Ales Musil <amusil@redhat.com> wrote:

> Considering following topology:
> client - sw0 - lrp0 - lr - lrp1 - sw1 - server
> sw0 in subnet 192.168.0.0/24
> sw1 in subnet 172.168.0.0/24
> SNAT configured for sw0 subnet
> gateway_mtu=1400 configured for lrp0
>
> If we send UDP traffic from client to server
> and server responds with packet bigger than 1400
> the following sequence will happen:
>
> 1) Packet is coming into lr via lrp1
> 2) unSNAT
> 3) Routing, the outport will be set to lrp1
> 4) Check for packet larger will fail
> 5) We will generate ICMP need frag
>
> However, the last step is wrong from the server
> perspective. The ICMP message will have IP source
> address = lrp1 IP address. Which means that SNAT won't
> happen because the source is not within the sw0 subnet,
> but the inner packet has sw0 subnet address, because it
> was unSNATted. This results in server ignoring the ICMP
> message because server never sent any packet to the
> sw0 subnet.
>
> To fix this issue use outport IP address as source instead
> of the inport one for the ICMP error message. This will
> lead to SNAT for the packet which will result in correct
> addresses on the sw1 side.
>
> Reported-at: https://issues.redhat.com/browse/FDP-39


I forgot to add (I'm sorry Ilya):
Co-Authored-By: Ilya Maximets <i.maximets@ovn.org>

If it needs v2 it will be included otherwise for mainters please include
this during merge.


>
> Signed-off-by: Ales Musil <amusil@redhat.com>
> ---
>  northd/northd.c          |  30 +++++---
>  tests/ovn-northd.at      |  65 ++++++++---------
>  tests/ovn.at             |   6 +-
>  tests/system-ovn-kmod.at | 152 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 210 insertions(+), 43 deletions(-)
>
> diff --git a/northd/northd.c b/northd/northd.c
> index 2a1f23fb9..1d306bb47 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -13894,7 +13894,15 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
> int mtu, struct hmap *lflows,
>                                                outport->json_key)
>                                    : NULL;
>
> -    if (op->lrp_networks.ipv4_addrs) {
> +    char *ip4_src = NULL;
> +
> +    if (outport && outport->lrp_networks.ipv4_addrs) {
> +        ip4_src = outport->lrp_networks.ipv4_addrs[0].addr_s;
> +    } else if (op->lrp_networks.ipv4_addrs) {
> +        ip4_src = op->lrp_networks.ipv4_addrs[0].addr_s;
> +    }
> +
> +    if (ip4_src) {
>          ds_clear(match);
>          ds_put_format(match, "inport == %s && %sip4 && "REGBIT_PKT_LARGER
>                        " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key,
> @@ -13914,9 +13922,8 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
> int mtu, struct hmap *lflows,
>              "icmp4.code = 4; /* Frag Needed and DF was Set. */ "
>              "icmp4.frag_mtu = %d; "
>              "next(pipeline=ingress, table=%d); };",
> -            op->lrp_networks.ea_s,
> -            op->lrp_networks.ipv4_addrs[0].addr_s,
> -            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
> +            op->lrp_networks.ea_s, ip4_src, mtu,
> +            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
>          ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
>                                    ds_cstr(match), ds_cstr(actions),
>                                    NULL,
> @@ -13927,7 +13934,15 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
> int mtu, struct hmap *lflows,
>                                    &op->nbrp->header_);
>      }
>
> -    if (op->lrp_networks.ipv6_addrs) {
> +    char *ip6_src = NULL;
> +
> +    if (outport && outport->lrp_networks.ipv6_addrs) {
> +        ip6_src = outport->lrp_networks.ipv6_addrs[0].addr_s;
> +    } else if (op->lrp_networks.ipv6_addrs) {
> +        ip6_src = op->lrp_networks.ipv6_addrs[0].addr_s;
> +    }
> +
> +    if (ip6_src) {
>          ds_clear(match);
>          ds_put_format(match, "inport == %s && %sip6 && "REGBIT_PKT_LARGER
>                        " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key,
> @@ -13947,9 +13962,8 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
> int mtu, struct hmap *lflows,
>              "icmp6.code = 0; "
>              "icmp6.frag_mtu = %d; "
>              "next(pipeline=ingress, table=%d); };",
> -            op->lrp_networks.ea_s,
> -            op->lrp_networks.ipv6_addrs[0].addr_s,
> -            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
> +            op->lrp_networks.ea_s, ip6_src, mtu,
> +            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
>          ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
>                                    ds_cstr(match), ds_cstr(actions),
>                                    NULL,
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 13c8a0d42..044d9c2a2 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -6106,10 +6106,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>  ])
>
>  AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort],
> [0], [dnl
> @@ -6137,10 +6137,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>  ])
>
>  AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort],
> [0], [dnl
> @@ -6166,10 +6166,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> "lr0-public" && (tcp)), action=(next;)
>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>  ])
>
>  AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" -e
> "tcp" | sort], [0], [dnl
> @@ -6191,14 +6191,14 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> "lr0-public" && (tcp)), action=(next;)
>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>  ])
>
>  AT_CHECK([grep "lr_in_admission.*check_pkt_larger" lr0flows | sort], [0],
> [dnl
> @@ -6230,14 +6230,14 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> "lr0-public" && (tcp)), action=(next;)
>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> "lr0-sw0" && (tcp)), action=(next;)
>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>  ])
>
>  AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" -e
> "tcp" | sort], [0], [dnl
> @@ -6256,15 +6256,16 @@ check ovn-nbctl --wait=sb clear
> logical_router_port lr0-public options
>  ovn-sbctl dump-flows lr0 > lr0flows
>  AT_CAPTURE_FILE([lr0flows])
>
> +grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed
> 's/table=../table=??/' | sort
>  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed
> 's/table=../table=??/' | sort], [0], [dnl
>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> "lr0-sw0" && (tcp)), action=(next;)
>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> table=0); };)
> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>  ])
>
>  check ovn-nbctl --wait=sb clear logical_router_port lr0-sw0 options
> diff --git a/tests/ovn.at b/tests/ovn.at
> index ba5ce298a..185f92cd7 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -20568,12 +20568,12 @@ test_ip_packet_larger() {
>          expected=${expected}0000000000000000000000000000
>          echo $expected > br_phys_n1.expected
>      else
> -        src_ip=`ip_to_hex 10 0 0 1`
> +        src_ip=`ip_to_hex 172.168.0.100`
>          dst_ip=`ip_to_hex 10 0 0 3`
>          # pkt len should be 146 (28 (icmp packet) + 118 (orig ip +
> payload))
>          reply_pkt_len=008e
>          ip_csum=fc97
> -
> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01686b
> +
> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01c55f
>
>  icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000$(printf
> "%04x" $mtu)
>          icmp_reply=${icmp_reply}4500${pkt_len}000000003f01c4dd
>          icmp_reply=${icmp_reply}${orig_packet_l3}
> @@ -20665,7 +20665,7 @@ test_ip6_packet_larger() {
>
>      local ipv6_src=10000000000000000000000000000003
>      local ipv6_dst=20000000000000000000000000000002
> -    local ipv6_rt=10000000000000000000000000000001
> +    local ipv6_rt=20000000000000000000000000000001
>
>      local payload=0000000000000000000000000000000000000000
>      local payload=${payload}0000000000000000000000000000000000000000
> diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at
> index b29e6b55a..333e0c7b8 100644
> --- a/tests/system-ovn-kmod.at
> +++ b/tests/system-ovn-kmod.at
> @@ -1115,3 +1115,155 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port
> patch-.*/d
>  /connection dropped.*/d"])
>  AT_CLEANUP
>  ])
> +
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([LR with SNAT fragmentation needed for external server])
> +AT_KEYWORDS([ovnlb])
> +
> +CHECK_CONNTRACK()
> +CHECK_CONNTRACK_NAT()
> +
> +ovn_start
> +OVS_TRAFFIC_VSWITCHD_START()
> +ADD_BR([br-int])
> +ADD_BR([br-ext])
> +
> +dnl Logical network:
> +dnl 2 logical switches "public" (192.168.1.0/24) and "internal" (
> 172.16.1.0/24)
> +dnl connected to a router lr.
> +dnl internal has a client.
> +dnl server is connected through localnet.
> +dnl
> +dnl Server IP 192.168.1.2 MTU 900
> +dnl Client IP  172.16.1.2 MTU 800
> +dnl
> +dnl SNAT for internal 172.16.1.2/24 with router ip 192.168.1.1.
> +
> +check ovs-ofctl add-flow br-ext action=normal
> +# Set external-ids in br-int needed for ovn-controller
> +check ovs-vsctl \
> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
> +        -- set Open_vSwitch .
> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> +        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true \
> +        -- set Open_vSwitch .
> external-ids:ovn-bridge-mappings=phynet:br-ext
> +
> +dnl Start ovn-controller
> +start_daemon ovn-controller
> +
> +check ovn-nbctl lr-add lr
> +check ovn-nbctl ls-add internal
> +check ovn-nbctl ls-add public
> +
> +check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24
> +check ovn-nbctl lsp-add  public pub-lr -- set Logical_Switch_Port pub-lr \
> +    type=router options:router-port=lr-pub addresses=\"00:00:01:01:02:03\"
> +
> +check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24
> +check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port
> internal-lr \
> +    type=router options:router-port=lr-internal
> addresses=\"00:00:01:01:02:04\"
> +
> +ovn-nbctl lsp-add public ln_port \
> +                -- lsp-set-addresses ln_port unknown \
> +                -- lsp-set-type ln_port localnet \
> +                -- lsp-set-options ln_port network_name=phynet
> +
> +ADD_NAMESPACES(server)
> +ADD_VETH([server], [server], [br-ext], ["192.168.1.2/24"],
> +         ["f0:00:00:01:02:03"], ["192.168.1.1"])
> +NS_EXEC([server], [ip l set dev server mtu 900])
> +NS_EXEC([server], [ip l show dev server])
> +
> +ADD_NAMESPACES(client)
> +ADD_VETH([client], [client], [br-int], ["172.16.1.2/24"],
> +         ["f0:00:0f:01:02:03"], ["172.16.1.1"])
> +NS_EXEC([client], [ip l set dev client mtu 800])
> +NS_EXEC([client], [ip l show dev client])
> +check ovn-nbctl lsp-add internal client \
> +  -- lsp-set-addresses client "f0:00:0f:01:02:03 172.16.1.2"
> +
> +dnl Config OVN load-balancer with a VIP.  (not necessary, but if we do not
> +dnl have a load balancer and comment out snat, we will receive a stray
> fragment
> +dnl on the client side.)
> +dnl check ovn-nbctl lb-add lb1 192.168.1.20:4242 172.16.1.2:4242 udp
> +dnl check ovn-nbctl lr-lb-add lr lb1
> +check ovn-nbctl set logical_router lr options:chassis=hv1
> +check ovn-nbctl set logical_router_port lr-internal
> options:gateway_mtu=800
> +
> +check ovn-nbctl lr-nat-add lr snat 192.168.1.1 172.16.1.2/24
> +
> +check ovn-nbctl --wait=hv sync
> +
> +ovn-nbctl show
> +ovs-vsctl show
> +ovn-appctl -t ovn-controller vlog/set vconn:file:dbg pinctrl:file:dbg
> +
> +AT_DATA([server.py], [dnl
> +import socket
> +
> +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> +
> +server_address = '192.168.1.2'
> +server_port = 4242
> +
> +server = (server_address, server_port)
> +sock.bind(server)
> +print("Listening on ", server_address, ":", str(server_port), flush=True)
> +
> +while True:
> +  payload, client_address = sock.recvfrom(1000)
> +  print("Received data from ", str(client_address), ": ", payload)
> +  sent = sock.sendto(b"x" * 1017, client_address)
> +  print("Sent back: ", str(sent), "bytes", flush=True)
> +])
> +NETNS_DAEMONIZE([server], [$PYTHON3 ./server.py > server.log],
> [server.pid])
> +
> +dnl Collect packets on server side.
> +NETNS_DAEMONIZE([server], [tcpdump -l -U -i server -vnne \
> +          'icmp or udp' > server.tcpdump 2>server_err], [tcpdump0.pid])
> +OVS_WAIT_UNTIL([grep "listening" server_err])
> +
> +dnl Collect packets on client side.
> +NETNS_DAEMONIZE([client], [tcpdump -l -U -i client -vnne \
> +          'icmp or udp' > client.tcpdump 2>client_err], [tcpdump1.pid])
> +OVS_WAIT_UNTIL([grep "listening" client_err])
> +
> +dnl Send two packets to the server with a short interval.
> +dnl First packet should generate 'needs frag', the second should result in
> +dnl corectly fragmented reply.
> +AT_DATA([client.py], [dnl
> +import socket
> +import time
> +
> +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> +sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
> +time.sleep(1)
> +sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
> +time.sleep(5)
> +])
> +NS_CHECK_EXEC([client], [$PYTHON3 ./client.py])
> +
> +dnl Expecting 2 outgoing packets and 2 fragments back - 8 lines total.
> +OVS_WAIT_UNTIL([test "$(cat client.tcpdump | wc -l)" = "8"])
> +
> +ovn-appctl -t ovn-controller vlog/set info
> +
> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
> +
> +as ovn-sb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as ovn-nb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as northd
> +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
> +
> +as
> +OVS_TRAFFIC_VSWITCHD_STOP(["
> +  /failed to query port patch-.*/d
> +  /connection dropped.*/d
> +"])
> +AT_CLEANUP
> +])
> --
> 2.41.0
>
>
Dumitru Ceara Oct. 9, 2023, 3:29 p.m. UTC | #2
On 9/20/23 09:37, Ales Musil wrote:
> On Wed, Sep 20, 2023 at 8:21 AM Ales Musil <amusil@redhat.com> wrote:
> 
>> Considering following topology:
>> client - sw0 - lrp0 - lr - lrp1 - sw1 - server
>> sw0 in subnet 192.168.0.0/24
>> sw1 in subnet 172.168.0.0/24
>> SNAT configured for sw0 subnet
>> gateway_mtu=1400 configured for lrp0
>>
>> If we send UDP traffic from client to server
>> and server responds with packet bigger than 1400
>> the following sequence will happen:
>>
>> 1) Packet is coming into lr via lrp1
>> 2) unSNAT
>> 3) Routing, the outport will be set to lrp1

I guess you meant lrp0 here, right?

>> 4) Check for packet larger will fail
>> 5) We will generate ICMP need frag
>>
>> However, the last step is wrong from the server
>> perspective. The ICMP message will have IP source
>> address = lrp1 IP address. Which means that SNAT won't
>> happen because the source is not within the sw0 subnet,
>> but the inner packet has sw0 subnet address, because it
>> was unSNATted. This results in server ignoring the ICMP
>> message because server never sent any packet to the
>> sw0 subnet.
>>
>> To fix this issue use outport IP address as source instead
>> of the inport one for the ICMP error message. This will
>> lead to SNAT for the packet which will result in correct
>> addresses on the sw1 side.
>>
>> Reported-at: https://issues.redhat.com/browse/FDP-39
> 
> 
> I forgot to add (I'm sorry Ilya):
> Co-Authored-By: Ilya Maximets <i.maximets@ovn.org>
> 
> If it needs v2 it will be included otherwise for mainters please include
> this during merge.
> 

I don't think v2 is needed, I can take care of this during merge; I'm
just waiting for an answer to the question I had above.

Thanks,
Dumitru

> 
>>
>> Signed-off-by: Ales Musil <amusil@redhat.com>
>> ---
>>  northd/northd.c          |  30 +++++---
>>  tests/ovn-northd.at      |  65 ++++++++---------
>>  tests/ovn.at             |   6 +-
>>  tests/system-ovn-kmod.at | 152 +++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 210 insertions(+), 43 deletions(-)
>>
>> diff --git a/northd/northd.c b/northd/northd.c
>> index 2a1f23fb9..1d306bb47 100644
>> --- a/northd/northd.c
>> +++ b/northd/northd.c
>> @@ -13894,7 +13894,15 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
>> int mtu, struct hmap *lflows,
>>                                                outport->json_key)
>>                                    : NULL;
>>
>> -    if (op->lrp_networks.ipv4_addrs) {
>> +    char *ip4_src = NULL;
>> +
>> +    if (outport && outport->lrp_networks.ipv4_addrs) {
>> +        ip4_src = outport->lrp_networks.ipv4_addrs[0].addr_s;
>> +    } else if (op->lrp_networks.ipv4_addrs) {
>> +        ip4_src = op->lrp_networks.ipv4_addrs[0].addr_s;
>> +    }
>> +
>> +    if (ip4_src) {
>>          ds_clear(match);
>>          ds_put_format(match, "inport == %s && %sip4 && "REGBIT_PKT_LARGER
>>                        " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key,
>> @@ -13914,9 +13922,8 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
>> int mtu, struct hmap *lflows,
>>              "icmp4.code = 4; /* Frag Needed and DF was Set. */ "
>>              "icmp4.frag_mtu = %d; "
>>              "next(pipeline=ingress, table=%d); };",
>> -            op->lrp_networks.ea_s,
>> -            op->lrp_networks.ipv4_addrs[0].addr_s,
>> -            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
>> +            op->lrp_networks.ea_s, ip4_src, mtu,
>> +            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
>>          ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
>>                                    ds_cstr(match), ds_cstr(actions),
>>                                    NULL,
>> @@ -13927,7 +13934,15 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
>> int mtu, struct hmap *lflows,
>>                                    &op->nbrp->header_);
>>      }
>>
>> -    if (op->lrp_networks.ipv6_addrs) {
>> +    char *ip6_src = NULL;
>> +
>> +    if (outport && outport->lrp_networks.ipv6_addrs) {
>> +        ip6_src = outport->lrp_networks.ipv6_addrs[0].addr_s;
>> +    } else if (op->lrp_networks.ipv6_addrs) {
>> +        ip6_src = op->lrp_networks.ipv6_addrs[0].addr_s;
>> +    }
>> +
>> +    if (ip6_src) {
>>          ds_clear(match);
>>          ds_put_format(match, "inport == %s && %sip6 && "REGBIT_PKT_LARGER
>>                        " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key,
>> @@ -13947,9 +13962,8 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
>> int mtu, struct hmap *lflows,
>>              "icmp6.code = 0; "
>>              "icmp6.frag_mtu = %d; "
>>              "next(pipeline=ingress, table=%d); };",
>> -            op->lrp_networks.ea_s,
>> -            op->lrp_networks.ipv6_addrs[0].addr_s,
>> -            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
>> +            op->lrp_networks.ea_s, ip6_src, mtu,
>> +            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
>>          ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
>>                                    ds_cstr(match), ds_cstr(actions),
>>                                    NULL,
>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>> index 13c8a0d42..044d9c2a2 100644
>> --- a/tests/ovn-northd.at
>> +++ b/tests/ovn-northd.at
>> @@ -6106,10 +6106,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
>> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
>>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
>> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
>>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>>  ])
>>
>>  AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort],
>> [0], [dnl
>> @@ -6137,10 +6137,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
>> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
>>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
>> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
>>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>>  ])
>>
>>  AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort],
>> [0], [dnl
>> @@ -6166,10 +6166,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
>> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
>> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
>>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
>> "lr0-public" && (tcp)), action=(next;)
>>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>>  ])
>>
>>  AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" -e
>> "tcp" | sort], [0], [dnl
>> @@ -6191,14 +6191,14 @@ AT_CHECK([grep -e "chk_pkt_len" -e
>> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
>> "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
>>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
>> "lr0-public" && (tcp)), action=(next;)
>>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>>  ])
>>
>>  AT_CHECK([grep "lr_in_admission.*check_pkt_larger" lr0flows | sort], [0],
>> [dnl
>> @@ -6230,14 +6230,14 @@ AT_CHECK([grep -e "chk_pkt_len" -e
>> "lr_in_larger_pkts" lr0flows | sed 's/table=.
>>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
>> "lr0-public" && (tcp)), action=(next;)
>>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
>> "lr0-sw0" && (tcp)), action=(next;)
>>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>>  ])
>>
>>  AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" -e
>> "tcp" | sort], [0], [dnl
>> @@ -6256,15 +6256,16 @@ check ovn-nbctl --wait=sb clear
>> logical_router_port lr0-public options
>>  ovn-sbctl dump-flows lr0 > lr0flows
>>  AT_CAPTURE_FILE([lr0flows])
>>
>> +grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed
>> 's/table=../table=??/' | sort
>>  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed
>> 's/table=../table=??/' | sort], [0], [dnl
>>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
>>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
>> "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
>>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
>> "lr0-sw0" && (tcp)), action=(next;)
>>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
>> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
>> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
>> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
>> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
>> table=0); };)
>> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
>> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0),
>> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
>> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
>> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
>> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
>>  ])
>>
>>  check ovn-nbctl --wait=sb clear logical_router_port lr0-sw0 options
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index ba5ce298a..185f92cd7 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -20568,12 +20568,12 @@ test_ip_packet_larger() {
>>          expected=${expected}0000000000000000000000000000
>>          echo $expected > br_phys_n1.expected
>>      else
>> -        src_ip=`ip_to_hex 10 0 0 1`
>> +        src_ip=`ip_to_hex 172.168.0.100`
>>          dst_ip=`ip_to_hex 10 0 0 3`
>>          # pkt len should be 146 (28 (icmp packet) + 118 (orig ip +
>> payload))
>>          reply_pkt_len=008e
>>          ip_csum=fc97
>> -
>> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01686b
>> +
>> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01c55f
>>
>>  icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000$(printf
>> "%04x" $mtu)
>>          icmp_reply=${icmp_reply}4500${pkt_len}000000003f01c4dd
>>          icmp_reply=${icmp_reply}${orig_packet_l3}
>> @@ -20665,7 +20665,7 @@ test_ip6_packet_larger() {
>>
>>      local ipv6_src=10000000000000000000000000000003
>>      local ipv6_dst=20000000000000000000000000000002
>> -    local ipv6_rt=10000000000000000000000000000001
>> +    local ipv6_rt=20000000000000000000000000000001
>>
>>      local payload=0000000000000000000000000000000000000000
>>      local payload=${payload}0000000000000000000000000000000000000000
>> diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at
>> index b29e6b55a..333e0c7b8 100644
>> --- a/tests/system-ovn-kmod.at
>> +++ b/tests/system-ovn-kmod.at
>> @@ -1115,3 +1115,155 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port
>> patch-.*/d
>>  /connection dropped.*/d"])
>>  AT_CLEANUP
>>  ])
>> +
>> +OVN_FOR_EACH_NORTHD([
>> +AT_SETUP([LR with SNAT fragmentation needed for external server])
>> +AT_KEYWORDS([ovnlb])
>> +
>> +CHECK_CONNTRACK()
>> +CHECK_CONNTRACK_NAT()
>> +
>> +ovn_start
>> +OVS_TRAFFIC_VSWITCHD_START()
>> +ADD_BR([br-int])
>> +ADD_BR([br-ext])
>> +
>> +dnl Logical network:
>> +dnl 2 logical switches "public" (192.168.1.0/24) and "internal" (
>> 172.16.1.0/24)
>> +dnl connected to a router lr.
>> +dnl internal has a client.
>> +dnl server is connected through localnet.
>> +dnl
>> +dnl Server IP 192.168.1.2 MTU 900
>> +dnl Client IP  172.16.1.2 MTU 800
>> +dnl
>> +dnl SNAT for internal 172.16.1.2/24 with router ip 192.168.1.1.
>> +
>> +check ovs-ofctl add-flow br-ext action=normal
>> +# Set external-ids in br-int needed for ovn-controller
>> +check ovs-vsctl \
>> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
>> +        -- set Open_vSwitch .
>> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
>> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
>> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
>> +        -- set bridge br-int fail-mode=secure
>> other-config:disable-in-band=true \
>> +        -- set Open_vSwitch .
>> external-ids:ovn-bridge-mappings=phynet:br-ext
>> +
>> +dnl Start ovn-controller
>> +start_daemon ovn-controller
>> +
>> +check ovn-nbctl lr-add lr
>> +check ovn-nbctl ls-add internal
>> +check ovn-nbctl ls-add public
>> +
>> +check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24
>> +check ovn-nbctl lsp-add  public pub-lr -- set Logical_Switch_Port pub-lr \
>> +    type=router options:router-port=lr-pub addresses=\"00:00:01:01:02:03\"
>> +
>> +check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24
>> +check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port
>> internal-lr \
>> +    type=router options:router-port=lr-internal
>> addresses=\"00:00:01:01:02:04\"
>> +
>> +ovn-nbctl lsp-add public ln_port \
>> +                -- lsp-set-addresses ln_port unknown \
>> +                -- lsp-set-type ln_port localnet \
>> +                -- lsp-set-options ln_port network_name=phynet
>> +
>> +ADD_NAMESPACES(server)
>> +ADD_VETH([server], [server], [br-ext], ["192.168.1.2/24"],
>> +         ["f0:00:00:01:02:03"], ["192.168.1.1"])
>> +NS_EXEC([server], [ip l set dev server mtu 900])
>> +NS_EXEC([server], [ip l show dev server])
>> +
>> +ADD_NAMESPACES(client)
>> +ADD_VETH([client], [client], [br-int], ["172.16.1.2/24"],
>> +         ["f0:00:0f:01:02:03"], ["172.16.1.1"])
>> +NS_EXEC([client], [ip l set dev client mtu 800])
>> +NS_EXEC([client], [ip l show dev client])
>> +check ovn-nbctl lsp-add internal client \
>> +  -- lsp-set-addresses client "f0:00:0f:01:02:03 172.16.1.2"
>> +
>> +dnl Config OVN load-balancer with a VIP.  (not necessary, but if we do not
>> +dnl have a load balancer and comment out snat, we will receive a stray
>> fragment
>> +dnl on the client side.)
>> +dnl check ovn-nbctl lb-add lb1 192.168.1.20:4242 172.16.1.2:4242 udp
>> +dnl check ovn-nbctl lr-lb-add lr lb1
>> +check ovn-nbctl set logical_router lr options:chassis=hv1
>> +check ovn-nbctl set logical_router_port lr-internal
>> options:gateway_mtu=800
>> +
>> +check ovn-nbctl lr-nat-add lr snat 192.168.1.1 172.16.1.2/24
>> +
>> +check ovn-nbctl --wait=hv sync
>> +
>> +ovn-nbctl show
>> +ovs-vsctl show
>> +ovn-appctl -t ovn-controller vlog/set vconn:file:dbg pinctrl:file:dbg
>> +
>> +AT_DATA([server.py], [dnl
>> +import socket
>> +
>> +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>> +
>> +server_address = '192.168.1.2'
>> +server_port = 4242
>> +
>> +server = (server_address, server_port)
>> +sock.bind(server)
>> +print("Listening on ", server_address, ":", str(server_port), flush=True)
>> +
>> +while True:
>> +  payload, client_address = sock.recvfrom(1000)
>> +  print("Received data from ", str(client_address), ": ", payload)
>> +  sent = sock.sendto(b"x" * 1017, client_address)
>> +  print("Sent back: ", str(sent), "bytes", flush=True)
>> +])
>> +NETNS_DAEMONIZE([server], [$PYTHON3 ./server.py > server.log],
>> [server.pid])
>> +
>> +dnl Collect packets on server side.
>> +NETNS_DAEMONIZE([server], [tcpdump -l -U -i server -vnne \
>> +          'icmp or udp' > server.tcpdump 2>server_err], [tcpdump0.pid])
>> +OVS_WAIT_UNTIL([grep "listening" server_err])
>> +
>> +dnl Collect packets on client side.
>> +NETNS_DAEMONIZE([client], [tcpdump -l -U -i client -vnne \
>> +          'icmp or udp' > client.tcpdump 2>client_err], [tcpdump1.pid])
>> +OVS_WAIT_UNTIL([grep "listening" client_err])
>> +
>> +dnl Send two packets to the server with a short interval.
>> +dnl First packet should generate 'needs frag', the second should result in
>> +dnl corectly fragmented reply.
>> +AT_DATA([client.py], [dnl
>> +import socket
>> +import time
>> +
>> +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>> +sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
>> +time.sleep(1)
>> +sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
>> +time.sleep(5)
>> +])
>> +NS_CHECK_EXEC([client], [$PYTHON3 ./client.py])
>> +
>> +dnl Expecting 2 outgoing packets and 2 fragments back - 8 lines total.
>> +OVS_WAIT_UNTIL([test "$(cat client.tcpdump | wc -l)" = "8"])
>> +
>> +ovn-appctl -t ovn-controller vlog/set info
>> +
>> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
>> +
>> +as ovn-sb
>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>> +
>> +as ovn-nb
>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>> +
>> +as northd
>> +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
>> +
>> +as
>> +OVS_TRAFFIC_VSWITCHD_STOP(["
>> +  /failed to query port patch-.*/d
>> +  /connection dropped.*/d
>> +"])
>> +AT_CLEANUP
>> +])
>> --
>> 2.41.0
>>
>>
>
Ales Musil Oct. 10, 2023, 5:42 a.m. UTC | #3
On Mon, Oct 9, 2023 at 5:29 PM Dumitru Ceara <dceara@redhat.com> wrote:

> On 9/20/23 09:37, Ales Musil wrote:
> > On Wed, Sep 20, 2023 at 8:21 AM Ales Musil <amusil@redhat.com> wrote:
> >
> >> Considering following topology:
> >> client - sw0 - lrp0 - lr - lrp1 - sw1 - server
> >> sw0 in subnet 192.168.0.0/24
> >> sw1 in subnet 172.168.0.0/24
> >> SNAT configured for sw0 subnet
> >> gateway_mtu=1400 configured for lrp0
> >>
> >> If we send UDP traffic from client to server
> >> and server responds with packet bigger than 1400
> >> the following sequence will happen:
> >>
> >> 1) Packet is coming into lr via lrp1
> >> 2) unSNAT
> >> 3) Routing, the outport will be set to lrp1
>
> I guess you meant lrp0 here, right?
>

Yes, sorry about that.


>
> >> 4) Check for packet larger will fail
> >> 5) We will generate ICMP need frag
> >>
> >> However, the last step is wrong from the server
> >> perspective. The ICMP message will have IP source
> >> address = lrp1 IP address. Which means that SNAT won't
> >> happen because the source is not within the sw0 subnet,
> >> but the inner packet has sw0 subnet address, because it
> >> was unSNATted. This results in server ignoring the ICMP
> >> message because server never sent any packet to the
> >> sw0 subnet.
> >>
> >> To fix this issue use outport IP address as source instead
> >> of the inport one for the ICMP error message. This will
> >> lead to SNAT for the packet which will result in correct
> >> addresses on the sw1 side.
> >>
> >> Reported-at: https://issues.redhat.com/browse/FDP-39
> >
> >
> > I forgot to add (I'm sorry Ilya):
> > Co-Authored-By: Ilya Maximets <i.maximets@ovn.org>
> >
> > If it needs v2 it will be included otherwise for mainters please include
> > this during merge.
> >
>
> I don't think v2 is needed, I can take care of this during merge; I'm
> just waiting for an answer to the question I had above.
>

That would be nice.


>
> Thanks,
> Dumitru
>

> >
> >>
> >> Signed-off-by: Ales Musil <amusil@redhat.com>
> >> ---
> >>  northd/northd.c          |  30 +++++---
> >>  tests/ovn-northd.at      |  65 ++++++++---------
> >>  tests/ovn.at             |   6 +-
> >>  tests/system-ovn-kmod.at | 152 +++++++++++++++++++++++++++++++++++++++
> >>  4 files changed, 210 insertions(+), 43 deletions(-)
> >>
> >> diff --git a/northd/northd.c b/northd/northd.c
> >> index 2a1f23fb9..1d306bb47 100644
> >> --- a/northd/northd.c
> >> +++ b/northd/northd.c
> >> @@ -13894,7 +13894,15 @@ build_icmperr_pkt_big_flows(struct ovn_port
> *op,
> >> int mtu, struct hmap *lflows,
> >>                                                outport->json_key)
> >>                                    : NULL;
> >>
> >> -    if (op->lrp_networks.ipv4_addrs) {
> >> +    char *ip4_src = NULL;
> >> +
> >> +    if (outport && outport->lrp_networks.ipv4_addrs) {
> >> +        ip4_src = outport->lrp_networks.ipv4_addrs[0].addr_s;
> >> +    } else if (op->lrp_networks.ipv4_addrs) {
> >> +        ip4_src = op->lrp_networks.ipv4_addrs[0].addr_s;
> >> +    }
> >> +
> >> +    if (ip4_src) {
> >>          ds_clear(match);
> >>          ds_put_format(match, "inport == %s && %sip4 &&
> "REGBIT_PKT_LARGER
> >>                        " && "REGBIT_EGRESS_LOOPBACK" == 0",
> op->json_key,
> >> @@ -13914,9 +13922,8 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
> >> int mtu, struct hmap *lflows,
> >>              "icmp4.code = 4; /* Frag Needed and DF was Set. */ "
> >>              "icmp4.frag_mtu = %d; "
> >>              "next(pipeline=ingress, table=%d); };",
> >> -            op->lrp_networks.ea_s,
> >> -            op->lrp_networks.ipv4_addrs[0].addr_s,
> >> -            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
> >> +            op->lrp_networks.ea_s, ip4_src, mtu,
> >> +            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
> >>          ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
> >>                                    ds_cstr(match), ds_cstr(actions),
> >>                                    NULL,
> >> @@ -13927,7 +13934,15 @@ build_icmperr_pkt_big_flows(struct ovn_port
> *op,
> >> int mtu, struct hmap *lflows,
> >>                                    &op->nbrp->header_);
> >>      }
> >>
> >> -    if (op->lrp_networks.ipv6_addrs) {
> >> +    char *ip6_src = NULL;
> >> +
> >> +    if (outport && outport->lrp_networks.ipv6_addrs) {
> >> +        ip6_src = outport->lrp_networks.ipv6_addrs[0].addr_s;
> >> +    } else if (op->lrp_networks.ipv6_addrs) {
> >> +        ip6_src = op->lrp_networks.ipv6_addrs[0].addr_s;
> >> +    }
> >> +
> >> +    if (ip6_src) {
> >>          ds_clear(match);
> >>          ds_put_format(match, "inport == %s && %sip6 &&
> "REGBIT_PKT_LARGER
> >>                        " && "REGBIT_EGRESS_LOOPBACK" == 0",
> op->json_key,
> >> @@ -13947,9 +13962,8 @@ build_icmperr_pkt_big_flows(struct ovn_port *op,
> >> int mtu, struct hmap *lflows,
> >>              "icmp6.code = 0; "
> >>              "icmp6.frag_mtu = %d; "
> >>              "next(pipeline=ingress, table=%d); };",
> >> -            op->lrp_networks.ea_s,
> >> -            op->lrp_networks.ipv6_addrs[0].addr_s,
> >> -            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
> >> +            op->lrp_networks.ea_s, ip6_src, mtu,
> >> +            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
> >>          ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
> >>                                    ds_cstr(match), ds_cstr(actions),
> >>                                    NULL,
> >> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> >> index 13c8a0d42..044d9c2a2 100644
> >> --- a/tests/ovn-northd.at
> >> +++ b/tests/ovn-northd.at
> >> @@ -6106,10 +6106,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> >> "lr_in_larger_pkts" lr0flows | sed 's/table=.
> >>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1),
> action=(next;)
> >>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> >> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
> >>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1),
> action=(next;)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >>  ])
> >>
> >>  AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort],
> >> [0], [dnl
> >> @@ -6137,10 +6137,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> >> "lr_in_larger_pkts" lr0flows | sed 's/table=.
> >>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1),
> action=(next;)
> >>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> >> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
> >>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1),
> action=(next;)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >>  ])
> >>
> >>  AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort],
> >> [0], [dnl
> >> @@ -6166,10 +6166,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> >> "lr_in_larger_pkts" lr0flows | sed 's/table=.
> >>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> >> "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
> >>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> >> "lr0-public" && (tcp)), action=(next;)
> >>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1),
> action=(next;)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >>  ])
> >>
> >>  AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger"
> -e
> >> "tcp" | sort], [0], [dnl
> >> @@ -6191,14 +6191,14 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> >> "lr_in_larger_pkts" lr0flows | sed 's/table=.
> >>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> >> "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
> >>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> >> "lr0-public" && (tcp)), action=(next;)
> >>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1),
> action=(next;)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >>  ])
> >>
> >>  AT_CHECK([grep "lr_in_admission.*check_pkt_larger" lr0flows | sort],
> [0],
> >> [dnl
> >> @@ -6230,14 +6230,14 @@ AT_CHECK([grep -e "chk_pkt_len" -e
> >> "lr_in_larger_pkts" lr0flows | sed 's/table=.
> >>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> >> "lr0-public" && (tcp)), action=(next;)
> >>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> >> "lr0-sw0" && (tcp)), action=(next;)
> >>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1),
> action=(next;)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >>  ])
> >>
> >>  AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger"
> -e
> >> "tcp" | sort], [0], [dnl
> >> @@ -6256,15 +6256,16 @@ check ovn-nbctl --wait=sb clear
> >> logical_router_port lr0-public options
> >>  ovn-sbctl dump-flows lr0 > lr0flows
> >>  AT_CAPTURE_FILE([lr0flows])
> >>
> >> +grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed
> >> 's/table=../table=??/' | sort
> >>  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed
> >> 's/table=../table=??/' | sort], [0], [dnl
> >>    table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1),
> action=(next;)
> >>    table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport ==
> >> "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
> >>    table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport ==
> >> "lr0-sw0" && (tcp)), action=(next;)
> >>    table=??(lr_in_larger_pkts  ), priority=0    , match=(1),
> action=(next;)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl =
> >> 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /*
> Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src =
> fe80::200:20ff:fe20:1213;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> -  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> >> 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255;
> >> icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag
> >> Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress,
> >> table=0); };)
> >> +  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport ==
> >> "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] ==
> 0),
> >> action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst =
> >> 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01;
> >> ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0;
> >> icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
> >>  ])
> >>
> >>  check ovn-nbctl --wait=sb clear logical_router_port lr0-sw0 options
> >> diff --git a/tests/ovn.at b/tests/ovn.at
> >> index ba5ce298a..185f92cd7 100644
> >> --- a/tests/ovn.at
> >> +++ b/tests/ovn.at
> >> @@ -20568,12 +20568,12 @@ test_ip_packet_larger() {
> >>          expected=${expected}0000000000000000000000000000
> >>          echo $expected > br_phys_n1.expected
> >>      else
> >> -        src_ip=`ip_to_hex 10 0 0 1`
> >> +        src_ip=`ip_to_hex 172.168.0.100`
> >>          dst_ip=`ip_to_hex 10 0 0 3`
> >>          # pkt len should be 146 (28 (icmp packet) + 118 (orig ip +
> >> payload))
> >>          reply_pkt_len=008e
> >>          ip_csum=fc97
> >> -
> >> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01686b
> >> +
> >> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01c55f
> >>
> >>  icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000$(printf
> >> "%04x" $mtu)
> >>          icmp_reply=${icmp_reply}4500${pkt_len}000000003f01c4dd
> >>          icmp_reply=${icmp_reply}${orig_packet_l3}
> >> @@ -20665,7 +20665,7 @@ test_ip6_packet_larger() {
> >>
> >>      local ipv6_src=10000000000000000000000000000003
> >>      local ipv6_dst=20000000000000000000000000000002
> >> -    local ipv6_rt=10000000000000000000000000000001
> >> +    local ipv6_rt=20000000000000000000000000000001
> >>
> >>      local payload=0000000000000000000000000000000000000000
> >>      local payload=${payload}0000000000000000000000000000000000000000
> >> diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at
> >> index b29e6b55a..333e0c7b8 100644
> >> --- a/tests/system-ovn-kmod.at
> >> +++ b/tests/system-ovn-kmod.at
> >> @@ -1115,3 +1115,155 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query
> port
> >> patch-.*/d
> >>  /connection dropped.*/d"])
> >>  AT_CLEANUP
> >>  ])
> >> +
> >> +OVN_FOR_EACH_NORTHD([
> >> +AT_SETUP([LR with SNAT fragmentation needed for external server])
> >> +AT_KEYWORDS([ovnlb])
> >> +
> >> +CHECK_CONNTRACK()
> >> +CHECK_CONNTRACK_NAT()
> >> +
> >> +ovn_start
> >> +OVS_TRAFFIC_VSWITCHD_START()
> >> +ADD_BR([br-int])
> >> +ADD_BR([br-ext])
> >> +
> >> +dnl Logical network:
> >> +dnl 2 logical switches "public" (192.168.1.0/24) and "internal" (
> >> 172.16.1.0/24)
> >> +dnl connected to a router lr.
> >> +dnl internal has a client.
> >> +dnl server is connected through localnet.
> >> +dnl
> >> +dnl Server IP 192.168.1.2 MTU 900
> >> +dnl Client IP  172.16.1.2 MTU 800
> >> +dnl
> >> +dnl SNAT for internal 172.16.1.2/24 with router ip 192.168.1.1.
> >> +
> >> +check ovs-ofctl add-flow br-ext action=normal
> >> +# Set external-ids in br-int needed for ovn-controller
> >> +check ovs-vsctl \
> >> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
> >> +        -- set Open_vSwitch .
> >> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> >> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> >> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> >> +        -- set bridge br-int fail-mode=secure
> >> other-config:disable-in-band=true \
> >> +        -- set Open_vSwitch .
> >> external-ids:ovn-bridge-mappings=phynet:br-ext
> >> +
> >> +dnl Start ovn-controller
> >> +start_daemon ovn-controller
> >> +
> >> +check ovn-nbctl lr-add lr
> >> +check ovn-nbctl ls-add internal
> >> +check ovn-nbctl ls-add public
> >> +
> >> +check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24
> >> +check ovn-nbctl lsp-add  public pub-lr -- set Logical_Switch_Port
> pub-lr \
> >> +    type=router options:router-port=lr-pub
> addresses=\"00:00:01:01:02:03\"
> >> +
> >> +check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24
> >> +check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port
> >> internal-lr \
> >> +    type=router options:router-port=lr-internal
> >> addresses=\"00:00:01:01:02:04\"
> >> +
> >> +ovn-nbctl lsp-add public ln_port \
> >> +                -- lsp-set-addresses ln_port unknown \
> >> +                -- lsp-set-type ln_port localnet \
> >> +                -- lsp-set-options ln_port network_name=phynet
> >> +
> >> +ADD_NAMESPACES(server)
> >> +ADD_VETH([server], [server], [br-ext], ["192.168.1.2/24"],
> >> +         ["f0:00:00:01:02:03"], ["192.168.1.1"])
> >> +NS_EXEC([server], [ip l set dev server mtu 900])
> >> +NS_EXEC([server], [ip l show dev server])
> >> +
> >> +ADD_NAMESPACES(client)
> >> +ADD_VETH([client], [client], [br-int], ["172.16.1.2/24"],
> >> +         ["f0:00:0f:01:02:03"], ["172.16.1.1"])
> >> +NS_EXEC([client], [ip l set dev client mtu 800])
> >> +NS_EXEC([client], [ip l show dev client])
> >> +check ovn-nbctl lsp-add internal client \
> >> +  -- lsp-set-addresses client "f0:00:0f:01:02:03 172.16.1.2"
> >> +
> >> +dnl Config OVN load-balancer with a VIP.  (not necessary, but if we do
> not
> >> +dnl have a load balancer and comment out snat, we will receive a stray
> >> fragment
> >> +dnl on the client side.)
> >> +dnl check ovn-nbctl lb-add lb1 192.168.1.20:4242 172.16.1.2:4242 udp
> >> +dnl check ovn-nbctl lr-lb-add lr lb1
> >> +check ovn-nbctl set logical_router lr options:chassis=hv1
> >> +check ovn-nbctl set logical_router_port lr-internal
> >> options:gateway_mtu=800
> >> +
> >> +check ovn-nbctl lr-nat-add lr snat 192.168.1.1 172.16.1.2/24
> >> +
> >> +check ovn-nbctl --wait=hv sync
> >> +
> >> +ovn-nbctl show
> >> +ovs-vsctl show
> >> +ovn-appctl -t ovn-controller vlog/set vconn:file:dbg pinctrl:file:dbg
> >> +
> >> +AT_DATA([server.py], [dnl
> >> +import socket
> >> +
> >> +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> >> +
> >> +server_address = '192.168.1.2'
> >> +server_port = 4242
> >> +
> >> +server = (server_address, server_port)
> >> +sock.bind(server)
> >> +print("Listening on ", server_address, ":", str(server_port),
> flush=True)
> >> +
> >> +while True:
> >> +  payload, client_address = sock.recvfrom(1000)
> >> +  print("Received data from ", str(client_address), ": ", payload)
> >> +  sent = sock.sendto(b"x" * 1017, client_address)
> >> +  print("Sent back: ", str(sent), "bytes", flush=True)
> >> +])
> >> +NETNS_DAEMONIZE([server], [$PYTHON3 ./server.py > server.log],
> >> [server.pid])
> >> +
> >> +dnl Collect packets on server side.
> >> +NETNS_DAEMONIZE([server], [tcpdump -l -U -i server -vnne \
> >> +          'icmp or udp' > server.tcpdump 2>server_err], [tcpdump0.pid])
> >> +OVS_WAIT_UNTIL([grep "listening" server_err])
> >> +
> >> +dnl Collect packets on client side.
> >> +NETNS_DAEMONIZE([client], [tcpdump -l -U -i client -vnne \
> >> +          'icmp or udp' > client.tcpdump 2>client_err], [tcpdump1.pid])
> >> +OVS_WAIT_UNTIL([grep "listening" client_err])
> >> +
> >> +dnl Send two packets to the server with a short interval.
> >> +dnl First packet should generate 'needs frag', the second should
> result in
> >> +dnl corectly fragmented reply.
> >> +AT_DATA([client.py], [dnl
> >> +import socket
> >> +import time
> >> +
> >> +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> >> +sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
> >> +time.sleep(1)
> >> +sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
> >> +time.sleep(5)
> >> +])
> >> +NS_CHECK_EXEC([client], [$PYTHON3 ./client.py])
> >> +
> >> +dnl Expecting 2 outgoing packets and 2 fragments back - 8 lines total.
> >> +OVS_WAIT_UNTIL([test "$(cat client.tcpdump | wc -l)" = "8"])
> >> +
> >> +ovn-appctl -t ovn-controller vlog/set info
> >> +
> >> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
> >> +
> >> +as ovn-sb
> >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >> +
> >> +as ovn-nb
> >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >> +
> >> +as northd
> >> +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
> >> +
> >> +as
> >> +OVS_TRAFFIC_VSWITCHD_STOP(["
> >> +  /failed to query port patch-.*/d
> >> +  /connection dropped.*/d
> >> +"])
> >> +AT_CLEANUP
> >> +])
> >> --
> >> 2.41.0
> >>
> >>
> >
>
>
Thanks,
Ales
Dumitru Ceara Oct. 10, 2023, 1:35 p.m. UTC | #4
On 10/10/23 07:42, Ales Musil wrote:
> 
> 
> On Mon, Oct 9, 2023 at 5:29 PM Dumitru Ceara <dceara@redhat.com
> <mailto:dceara@redhat.com>> wrote:
> 
>     On 9/20/23 09:37, Ales Musil wrote:
>     > On Wed, Sep 20, 2023 at 8:21 AM Ales Musil <amusil@redhat.com
>     <mailto:amusil@redhat.com>> wrote:
>     >
>     >> Considering following topology:
>     >> client - sw0 - lrp0 - lr - lrp1 - sw1 - server
>     >> sw0 in subnet 192.168.0.0/24 <http://192.168.0.0/24>
>     >> sw1 in subnet 172.168.0.0/24 <http://172.168.0.0/24>
>     >> SNAT configured for sw0 subnet
>     >> gateway_mtu=1400 configured for lrp0
>     >>
>     >> If we send UDP traffic from client to server
>     >> and server responds with packet bigger than 1400
>     >> the following sequence will happen:
>     >>
>     >> 1) Packet is coming into lr via lrp1
>     >> 2) unSNAT
>     >> 3) Routing, the outport will be set to lrp1
> 
>     I guess you meant lrp0 here, right?
> 
> 
> Yes, sorry about that.
>  
> 

OK, I fixed up the commit message and applied this patch to main and
backported it to all branches down to 22.03.

Regards,
Dumitru
diff mbox series

Patch

diff --git a/northd/northd.c b/northd/northd.c
index 2a1f23fb9..1d306bb47 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -13894,7 +13894,15 @@  build_icmperr_pkt_big_flows(struct ovn_port *op, int mtu, struct hmap *lflows,
                                               outport->json_key)
                                   : NULL;
 
-    if (op->lrp_networks.ipv4_addrs) {
+    char *ip4_src = NULL;
+
+    if (outport && outport->lrp_networks.ipv4_addrs) {
+        ip4_src = outport->lrp_networks.ipv4_addrs[0].addr_s;
+    } else if (op->lrp_networks.ipv4_addrs) {
+        ip4_src = op->lrp_networks.ipv4_addrs[0].addr_s;
+    }
+
+    if (ip4_src) {
         ds_clear(match);
         ds_put_format(match, "inport == %s && %sip4 && "REGBIT_PKT_LARGER
                       " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key,
@@ -13914,9 +13922,8 @@  build_icmperr_pkt_big_flows(struct ovn_port *op, int mtu, struct hmap *lflows,
             "icmp4.code = 4; /* Frag Needed and DF was Set. */ "
             "icmp4.frag_mtu = %d; "
             "next(pipeline=ingress, table=%d); };",
-            op->lrp_networks.ea_s,
-            op->lrp_networks.ipv4_addrs[0].addr_s,
-            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
+            op->lrp_networks.ea_s, ip4_src, mtu,
+            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
         ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
                                   ds_cstr(match), ds_cstr(actions),
                                   NULL,
@@ -13927,7 +13934,15 @@  build_icmperr_pkt_big_flows(struct ovn_port *op, int mtu, struct hmap *lflows,
                                   &op->nbrp->header_);
     }
 
-    if (op->lrp_networks.ipv6_addrs) {
+    char *ip6_src = NULL;
+
+    if (outport && outport->lrp_networks.ipv6_addrs) {
+        ip6_src = outport->lrp_networks.ipv6_addrs[0].addr_s;
+    } else if (op->lrp_networks.ipv6_addrs) {
+        ip6_src = op->lrp_networks.ipv6_addrs[0].addr_s;
+    }
+
+    if (ip6_src) {
         ds_clear(match);
         ds_put_format(match, "inport == %s && %sip6 && "REGBIT_PKT_LARGER
                       " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key,
@@ -13947,9 +13962,8 @@  build_icmperr_pkt_big_flows(struct ovn_port *op, int mtu, struct hmap *lflows,
             "icmp6.code = 0; "
             "icmp6.frag_mtu = %d; "
             "next(pipeline=ingress, table=%d); };",
-            op->lrp_networks.ea_s,
-            op->lrp_networks.ipv6_addrs[0].addr_s,
-            mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
+            op->lrp_networks.ea_s, ip6_src, mtu,
+            ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
         ovn_lflow_add_with_hint__(lflows, op->od, stage, 150,
                                   ds_cstr(match), ds_cstr(actions),
                                   NULL,
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 13c8a0d42..044d9c2a2 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -6106,10 +6106,10 @@  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed 's/table=.
   table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
   table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
 ])
 
 AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort], [0], [dnl
@@ -6137,10 +6137,10 @@  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed 's/table=.
   table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
   table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
 ])
 
 AT_CHECK([grep -E "lr_in_admission.*check_pkt_larger" lr0flows | sort], [0], [dnl
@@ -6166,10 +6166,10 @@  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed 's/table=.
   table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); next;)
   table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport == "lr0-public" && (tcp)), action=(next;)
   table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
 ])
 
 AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" -e "tcp" | sort], [0], [dnl
@@ -6191,14 +6191,14 @@  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed 's/table=.
   table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
   table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport == "lr0-public" && (tcp)), action=(next;)
   table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
 ])
 
 AT_CHECK([grep "lr_in_admission.*check_pkt_larger" lr0flows | sort], [0], [dnl
@@ -6230,14 +6230,14 @@  AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed 's/table=.
   table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport == "lr0-public" && (tcp)), action=(next;)
   table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport == "lr0-sw0" && (tcp)), action=(next;)
   table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
 ])
 
 AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" -e "tcp" | sort], [0], [dnl
@@ -6256,15 +6256,16 @@  check ovn-nbctl --wait=sb clear logical_router_port lr0-public options
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CAPTURE_FILE([lr0flows])
 
+grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed 's/table=../table=??/' | sort
 AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sed 's/table=../table=??/' | sort], [0], [dnl
   table=??(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1414); next;)
   table=??(lr_in_chk_pkt_len  ), priority=55   , match=(outport == "lr0-sw0" && (tcp)), action=(next;)
   table=??(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
-  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=??(lr_in_larger_pkts  ), priority=150  , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
 ])
 
 check ovn-nbctl --wait=sb clear logical_router_port lr0-sw0 options
diff --git a/tests/ovn.at b/tests/ovn.at
index ba5ce298a..185f92cd7 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -20568,12 +20568,12 @@  test_ip_packet_larger() {
         expected=${expected}0000000000000000000000000000
         echo $expected > br_phys_n1.expected
     else
-        src_ip=`ip_to_hex 10 0 0 1`
+        src_ip=`ip_to_hex 172.168.0.100`
         dst_ip=`ip_to_hex 10 0 0 3`
         # pkt len should be 146 (28 (icmp packet) + 118 (orig ip + payload))
         reply_pkt_len=008e
         ip_csum=fc97
-        icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01686b
+        icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01c55f
         icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000$(printf "%04x" $mtu)
         icmp_reply=${icmp_reply}4500${pkt_len}000000003f01c4dd
         icmp_reply=${icmp_reply}${orig_packet_l3}
@@ -20665,7 +20665,7 @@  test_ip6_packet_larger() {
 
     local ipv6_src=10000000000000000000000000000003
     local ipv6_dst=20000000000000000000000000000002
-    local ipv6_rt=10000000000000000000000000000001
+    local ipv6_rt=20000000000000000000000000000001
 
     local payload=0000000000000000000000000000000000000000
     local payload=${payload}0000000000000000000000000000000000000000
diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at
index b29e6b55a..333e0c7b8 100644
--- a/tests/system-ovn-kmod.at
+++ b/tests/system-ovn-kmod.at
@@ -1115,3 +1115,155 @@  OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
 /connection dropped.*/d"])
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([LR with SNAT fragmentation needed for external server])
+AT_KEYWORDS([ovnlb])
+
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+
+ovn_start
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-int])
+ADD_BR([br-ext])
+
+dnl Logical network:
+dnl 2 logical switches "public" (192.168.1.0/24) and "internal" (172.16.1.0/24)
+dnl connected to a router lr.
+dnl internal has a client.
+dnl server is connected through localnet.
+dnl
+dnl Server IP 192.168.1.2 MTU 900
+dnl Client IP  172.16.1.2 MTU 800
+dnl
+dnl SNAT for internal 172.16.1.2/24 with router ip 192.168.1.1.
+
+check ovs-ofctl add-flow br-ext action=normal
+# Set external-ids in br-int needed for ovn-controller
+check ovs-vsctl \
+        -- set Open_vSwitch . external-ids:system-id=hv1 \
+        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
+        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
+        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \
+        -- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext
+
+dnl Start ovn-controller
+start_daemon ovn-controller
+
+check ovn-nbctl lr-add lr
+check ovn-nbctl ls-add internal
+check ovn-nbctl ls-add public
+
+check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24
+check ovn-nbctl lsp-add  public pub-lr -- set Logical_Switch_Port pub-lr \
+    type=router options:router-port=lr-pub addresses=\"00:00:01:01:02:03\"
+
+check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24
+check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port internal-lr \
+    type=router options:router-port=lr-internal addresses=\"00:00:01:01:02:04\"
+
+ovn-nbctl lsp-add public ln_port \
+                -- lsp-set-addresses ln_port unknown \
+                -- lsp-set-type ln_port localnet \
+                -- lsp-set-options ln_port network_name=phynet
+
+ADD_NAMESPACES(server)
+ADD_VETH([server], [server], [br-ext], ["192.168.1.2/24"],
+         ["f0:00:00:01:02:03"], ["192.168.1.1"])
+NS_EXEC([server], [ip l set dev server mtu 900])
+NS_EXEC([server], [ip l show dev server])
+
+ADD_NAMESPACES(client)
+ADD_VETH([client], [client], [br-int], ["172.16.1.2/24"],
+         ["f0:00:0f:01:02:03"], ["172.16.1.1"])
+NS_EXEC([client], [ip l set dev client mtu 800])
+NS_EXEC([client], [ip l show dev client])
+check ovn-nbctl lsp-add internal client \
+  -- lsp-set-addresses client "f0:00:0f:01:02:03 172.16.1.2"
+
+dnl Config OVN load-balancer with a VIP.  (not necessary, but if we do not
+dnl have a load balancer and comment out snat, we will receive a stray fragment
+dnl on the client side.)
+dnl check ovn-nbctl lb-add lb1 192.168.1.20:4242 172.16.1.2:4242 udp
+dnl check ovn-nbctl lr-lb-add lr lb1
+check ovn-nbctl set logical_router lr options:chassis=hv1
+check ovn-nbctl set logical_router_port lr-internal options:gateway_mtu=800
+
+check ovn-nbctl lr-nat-add lr snat 192.168.1.1 172.16.1.2/24
+
+check ovn-nbctl --wait=hv sync
+
+ovn-nbctl show
+ovs-vsctl show
+ovn-appctl -t ovn-controller vlog/set vconn:file:dbg pinctrl:file:dbg
+
+AT_DATA([server.py], [dnl
+import socket
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+server_address = '192.168.1.2'
+server_port = 4242
+
+server = (server_address, server_port)
+sock.bind(server)
+print("Listening on ", server_address, ":", str(server_port), flush=True)
+
+while True:
+  payload, client_address = sock.recvfrom(1000)
+  print("Received data from ", str(client_address), ": ", payload)
+  sent = sock.sendto(b"x" * 1017, client_address)
+  print("Sent back: ", str(sent), "bytes", flush=True)
+])
+NETNS_DAEMONIZE([server], [$PYTHON3 ./server.py > server.log], [server.pid])
+
+dnl Collect packets on server side.
+NETNS_DAEMONIZE([server], [tcpdump -l -U -i server -vnne \
+          'icmp or udp' > server.tcpdump 2>server_err], [tcpdump0.pid])
+OVS_WAIT_UNTIL([grep "listening" server_err])
+
+dnl Collect packets on client side.
+NETNS_DAEMONIZE([client], [tcpdump -l -U -i client -vnne \
+          'icmp or udp' > client.tcpdump 2>client_err], [tcpdump1.pid])
+OVS_WAIT_UNTIL([grep "listening" client_err])
+
+dnl Send two packets to the server with a short interval.
+dnl First packet should generate 'needs frag', the second should result in
+dnl corectly fragmented reply.
+AT_DATA([client.py], [dnl
+import socket
+import time
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
+time.sleep(1)
+sock.sendto(b"x" * 7, ("192.168.1.2", 4242))
+time.sleep(5)
+])
+NS_CHECK_EXEC([client], [$PYTHON3 ./client.py])
+
+dnl Expecting 2 outgoing packets and 2 fragments back - 8 lines total.
+OVS_WAIT_UNTIL([test "$(cat client.tcpdump | wc -l)" = "8"])
+
+ovn-appctl -t ovn-controller vlog/set info
+
+OVS_APP_EXIT_AND_WAIT([ovn-controller])
+
+as ovn-sb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as ovn-nb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as northd
+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["
+  /failed to query port patch-.*/d
+  /connection dropped.*/d
+"])
+AT_CLEANUP
+])