On Wed, Sep 20, 2023 at 8:21 AM Ales Musil <amu...@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.maxim...@ovn.org>

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


>
> Signed-off-by: Ales Musil <amu...@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

Senior Software Engineer - OVN Core

Red Hat EMEA <https://www.redhat.com>

amu...@redhat.com
<https://red.ht/sig>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to