On 7/9/26 7:10 PM, Mairtin O'Loingsigh via dev wrote:
> When transit traffic arrives on an l3dgw port with TTL=0 or TTL=1,
> northd generates an ICMP Time Exceeded reply. Previously, the action
> for l3dgw ports used "ip4.dst <-> ip4.src", which swaps the source
> and destination addresses. This sets the ICMP reply source to the
> original packet's destination, instead of the receiving router port
> address. For example, a packet from 203.0.113.50 destined to
> 10.0.0.5 would produce an ICMP error with source 10.0.0.5 instead
> of the router port's own address.
> 
> Use "ip4.dst = ip4.src; ip4.src = <router_port_ip>" and
> "eth.dst = eth.src; eth.src = %s" unconditionally
> for both l3dgw and non-l3dgw ports, so the ICMP reply MAC and IP
> address are always the router port's address in the matching subnet.
> 

Hi Mairtin, Ilya,

Thanks for the fix and reviews!

> Fixes: 4ecc61247d86 ("northd: fix ttl exceeded with FIP")
> Reported-at: https://redhat.atlassian.net/browse/FDP-4078

The correct link for our downstream automation is:
https://redhat.atlassian.net/browse/FDP-4083

> Signed-off-by: Mairtin O'Loingsigh <[email protected]>
> ---
> v2 -> v3:
>   - Rebase on main.
> v1 -> v2:
>   - Set source MAC to router port MAC.
> 
>  NEWS                |   2 +
>  northd/northd.c     |  68 ++++++++++++-------------
>  tests/ovn-northd.at | 119 ++++++++++++++++++++++++++++++++++----------
>  3 files changed, 128 insertions(+), 61 deletions(-)
> 
> diff --git a/NEWS b/NEWS
> index d1a6ad27f..797e289d3 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,5 +1,7 @@
>  Post v26.03.0
>  -------------
> +   - Fixed support for TTL expired. Use router port IP and MAC instead of 
> dest
> +     IP and MAC for ICMP Time exceeded response.

This is a bug fix, no need for the NEWS entry IMO.

I fixed this and the jira reference up and then applied the patch to
main and 26.03.

Regards,
Dumitru

>     - Load balancer health checks now "fail closed" for newly added backends:
>       ovn-northd initializes a newly created Service_Monitor row to the
>       "offline" state, so traffic is not forwarded to a backend until its 
> first
> diff --git a/northd/northd.c b/northd/northd.c
> index e4cd93969..16356c6ca 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -16947,19 +16947,9 @@ build_lrouter_ipv4_default_ttl_expired_flows(
>          return;
>      }
>  
> -    struct ds ip_ds = DS_EMPTY_INITIALIZER;
>      for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
>          ds_clear(match);
>          ds_clear(actions);
> -        ds_clear(&ip_ds);
> -        if (lrp_is_l3dgw(op)) {
> -            ds_put_cstr(&ip_ds, "ip4.dst <-> ip4.src");
> -            ds_put_format(match, "is_chassis_resident(%s) && ",
> -                          op->cr_port->json_key);
> -        } else {
> -            ds_put_format(&ip_ds, "ip4.dst = ip4.src; ip4.src = %s",
> -                          op->lrp_networks.ipv4_addrs[i].addr_s);
> -        }
>          ds_put_format(match,
>                        "inport == %s && ip4 && "
>                        "ip4.src == %s/%d && "
> @@ -16967,23 +16957,28 @@ build_lrouter_ipv4_default_ttl_expired_flows(
>                        op->json_key,
>                        op->lrp_networks.ipv4_addrs[i].network_s,
>                        op->lrp_networks.ipv4_addrs[i].plen);
> +        if (lrp_is_l3dgw(op)) {
> +            ds_put_format(match, " && is_chassis_resident(%s)",
> +                          op->cr_port->json_key);
> +        }
> +
>          ds_put_format(actions,
>                        "icmp4 {"
> -                      "eth.dst <-> eth.src; "
> +                      "eth.dst = eth.src; eth.src = %s; "
>                        "icmp4.type = 11; /* Time exceeded */ "
>                        "icmp4.code = 0; /* TTL exceeded in transit */ "
> -                      "%s ; ip.ttl = 254; "
> +                      "ip4.dst = ip4.src; ip4.src = %s; ip.ttl = 254; "
>                        "outport = %s; flags.loopback = 1; output; };",
> -                      ds_cstr(&ip_ds), op->json_key);
> +                      op->lrp_networks.ea_s,
> +                      op->lrp_networks.ipv4_addrs[i].addr_s, op->json_key);
> +
>          ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 31,
>                        ds_cstr(match), ds_cstr(actions), lflow_ref,
>                        WITH_CTRL_METER(copp_meter_get(COPP_ICMP4_ERR,
>                                                       op->od->nbr->copp,
>                                                       meter_groups)),
>                        WITH_HINT(&op->nbrp->header_));
> -
>      }
> -    ds_destroy(&ip_ds);
>      ds_clear(match);
>      ds_clear(actions);
>  
> @@ -16994,15 +16989,19 @@ build_lrouter_ipv4_default_ttl_expired_flows(
>                    "inport == %s && ip4 && "
>                    "ip.ttl == {0, 1} && !ip.later_frag",
>                    op->json_key);
> +    if (lrp_is_l3dgw(op)) {
> +        ds_put_format(match, " && is_chassis_resident(%s)",
> +                      op->cr_port->json_key);
> +    }
>      ds_put_format(actions,
>                    "icmp4 {"
> -                  "eth.dst <-> eth.src; "
> +                  "eth.dst = eth.src; eth.src = %s; "
>                    "icmp4.type = 11; /* Time exceeded */ "
>                    "icmp4.code = 0; /* TTL exceeded in transit */ "
>                    "ip4.dst = ip4.src; ip4.src = %s; ip.ttl = 254; "
> -                   "outport = %s; flags.loopback = 1; output; };",
> -                   op->lrp_networks.ipv4_addrs[0].addr_s,
> -                   op->json_key);
> +                  "outport = %s; flags.loopback = 1; output; };",
> +                  op->lrp_networks.ea_s, 
> op->lrp_networks.ipv4_addrs[0].addr_s,
> +                  op->json_key);
>      ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 30,
>                    ds_cstr(match), ds_cstr(actions), lflow_ref,
>                    WITH_CTRL_METER(copp_meter_get(COPP_ICMP4_ERR,
> @@ -17025,19 +17024,9 @@ build_lrouter_ipv6_default_ttl_expired_flows(
>          return;
>      }
>  
> -    struct ds ip_ds = DS_EMPTY_INITIALIZER;
>      for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs - 1; i++) {
>          ds_clear(match);
>          ds_clear(actions);
> -        ds_clear(&ip_ds);
> -        if (lrp_is_l3dgw(op)) {
> -            ds_put_cstr(&ip_ds, "ip6.dst <-> ip6.src");
> -            ds_put_format(match, "is_chassis_resident(%s) && ",
> -                          op->cr_port->json_key);
> -        } else {
> -            ds_put_format(&ip_ds, "ip6.dst = ip6.src; ip6.src = %s",
> -                          op->lrp_networks.ipv6_addrs[i].addr_s);
> -        }
>          ds_put_format(match,
>                        "inport == %s && ip6 && "
>                        "ip6.src == %s/%d && "
> @@ -17045,14 +17034,20 @@ build_lrouter_ipv6_default_ttl_expired_flows(
>                        op->json_key,
>                        op->lrp_networks.ipv6_addrs[i].network_s,
>                        op->lrp_networks.ipv6_addrs[i].plen);
> +        if (lrp_is_l3dgw(op)) {
> +            ds_put_format(match, " && is_chassis_resident(%s)",
> +                          op->cr_port->json_key);
> +        }
>          ds_put_format(actions,
>                        "icmp6 {"
> -                      "eth.dst <-> eth.src; "
> -                      "%s ; ip.ttl = 254; "
> +                      "eth.dst = eth.src; eth.src = %s; "
> +                      "ip6.dst = ip6.src; ip6.src = %s; ip.ttl = 254; "
>                        "icmp6.type = 3; /* Time exceeded */ "
>                        "icmp6.code = 0; /* TTL exceeded in transit */ "
>                        "outport = %s; flags.loopback = 1; output; };",
> -                      ds_cstr(&ip_ds), op->json_key);
> +                      op->lrp_networks.ea_s,
> +                      op->lrp_networks.ipv6_addrs[i].addr_s, op->json_key);
> +
>          ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 31,
>                        ds_cstr(match), ds_cstr(actions), lflow_ref,
>                        WITH_CTRL_METER(copp_meter_get(COPP_ICMP6_ERR,
> @@ -17060,7 +17055,6 @@ build_lrouter_ipv6_default_ttl_expired_flows(
>                                                       meter_groups)),
>                        WITH_HINT(&op->nbrp->header_));
>      }
> -    ds_destroy(&ip_ds);
>      ds_clear(match);
>      ds_clear(actions);
>  
> @@ -17071,14 +17065,18 @@ build_lrouter_ipv6_default_ttl_expired_flows(
>                    "inport == %s && ip6 && "
>                    "ip.ttl == {0, 1} && !ip.later_frag",
>                    op->json_key);
> +    if (lrp_is_l3dgw(op)) {
> +        ds_put_format(match, " && is_chassis_resident(%s)",
> +                      op->cr_port->json_key);
> +    }
>      ds_put_format(actions,
>                    "icmp6 {"
> -                  "eth.dst <-> eth.src; "
> +                  "eth.dst = eth.src; eth.src = %s; "
>                    "ip6.dst = ip6.src; ip6.src = %s; "
>                    "ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ "
>                    "icmp6.code = 0; /* TTL exceeded in transit */ "
>                    "outport = %s; flags.loopback = 1; output; };",
> -                  op->lrp_networks.ipv6_addrs[0].addr_s,
> +                  op->lrp_networks.ea_s, 
> op->lrp_networks.ipv6_addrs[0].addr_s,
>                    op->json_key);
>      ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 30,
>                    ds_cstr(match), ds_cstr(actions), lflow_ref,
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 2edcfc2cb..45e648e49 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -8608,14 +8608,14 @@ AT_CHECK([grep -e 'lr_in_ip_input    ' lrflows | grep 
> -e 'igmp' -e 'mld' -e 'ip.
>    table=??(lr_in_ip_input     ), priority=120  , match=((mldv1 || mldv2) && 
> ip.ttl == 1), action=(next;)
>    table=??(lr_in_ip_input     ), priority=120  , match=(igmp && ip.ttl == 
> 1), action=(next;)
>    table=??(lr_in_ip_input     ), priority=29   , match=(ip.ttl == {0, 1}), 
> action=(drop;)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp1" && 
> ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> 
> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded 
> in transit */ ip4.dst = ip4.src; ip4.src = 10.10.10.1; ip.ttl = 254; outport 
> = "lrp1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp1" && 
> ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> 
> eth.src; ip6.dst = ip6.src; ip6.src = 1010::1; ip.ttl = 254; icmp6.type = 3; 
> /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in transit */ outport = 
> "lrp1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp2" && 
> ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> 
> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded 
> in transit */ ip4.dst = ip4.src; ip4.src = 20.20.20.1; ip.ttl = 254; outport 
> = "lrp2"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp2" && 
> ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> 
> eth.src; ip6.dst = ip6.src; ip6.src = 2020::1; ip.ttl = 254; icmp6.type = 3; 
> /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in transit */ outport = 
> "lrp2"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp1" && 
> ip4 && ip4.src == 10.10.10.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 10.10.10.1 ; ip.ttl = 254; outport = "lrp1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp1" && 
> ip6 && ip6.src == 1010::/64 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp6 {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = 1010::1 ; 
> ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL 
> exceeded in transit */ outport = "lrp1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp2" && 
> ip4 && ip4.src == 20.20.20.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 20.20.20.1 ; ip.ttl = 254; outport = "lrp2"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp2" && 
> ip6 && ip6.src == 2020::/64 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp6 {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = 2020::1 ; 
> ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL 
> exceeded in transit */ outport = "lrp2"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp1" && 
> ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:00:01; icmp4.type = 11; /* Time exceeded */ icmp4.code 
> = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 10.10.10.1; 
> ip.ttl = 254; outport = "lrp1"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp1" && 
> ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:00:01; ip6.dst = ip6.src; ip6.src = 1010::1; ip.ttl = 
> 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in 
> transit */ outport = "lrp1"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp2" && 
> ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:00:02; icmp4.type = 11; /* Time exceeded */ icmp4.code 
> = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 20.20.20.1; 
> ip.ttl = 254; outport = "lrp2"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lrp2" && 
> ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:00:02; ip6.dst = ip6.src; ip6.src = 2020::1; ip.ttl = 
> 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in 
> transit */ outport = "lrp2"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp1" && 
> ip4 && ip4.src == 10.10.10.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst = eth.src; eth.src = 00:00:00:00:00:01; icmp4.type = 
> 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst 
> = ip4.src; ip4.src = 10.10.10.1; ip.ttl = 254; outport = "lrp1"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp1" && 
> ip6 && ip6.src == 1010::/64 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp6 {eth.dst = eth.src; eth.src = 00:00:00:00:00:01; ip6.dst = 
> ip6.src; ip6.src = 1010::1; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lrp1"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp2" && 
> ip4 && ip4.src == 20.20.20.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst = eth.src; eth.src = 00:00:00:00:00:02; icmp4.type = 
> 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst 
> = ip4.src; ip4.src = 20.20.20.1; ip.ttl = 254; outport = "lrp2"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lrp2" && 
> ip6 && ip6.src == 2020::/64 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp6 {eth.dst = eth.src; eth.src = 00:00:00:00:00:02; ip6.dst = 
> ip6.src; ip6.src = 2020::1; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lrp2"; 
> flags.loopback = 1; output; };)
>    table=??(lr_in_ip_input     ), priority=32   , match=(ip.ttl == {0, 1} && 
> !ip.later_frag && (ip4.mcast || ip6.mcast)), action=(drop;)
>  ])
>  
> @@ -8635,6 +8635,73 @@ OVN_CLEANUP_NORTHD
>  AT_CLEANUP
>  ])
>  
> +OVN_FOR_EACH_NORTHD_NO_HV([
> +AT_SETUP([TTL exceeded -- l3dgw port uses correct source IP])
> +AT_KEYWORDS([ttl-exceeded l3dgw])
> +ovn_start
> +
> +check ovn-nbctl lr-add lr0
> +check ovn-nbctl ls-add sw0
> +check ovn-nbctl ls-add public
> +
> +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24 
> 2001:db8::1/64
> +check ovn-nbctl lsp-add-router-port sw0 sw0-lr0 lr0-sw0
> +
> +check ovn-nbctl lrp-add lr0 lr0-public 00:00:00:00:ff:02 172.168.0.10/24 
> 2001:db8:1::1/64
> +check ovn-nbctl lsp-add-router-port public public-lr0 lr0-public
> +
> +check ovn-sbctl chassis-add gw1 geneve 127.0.0.1
> +check ovn-nbctl lrp-set-gateway-chassis lr0-public gw1
> +
> +check ovn-nbctl --wait=sb sync
> +
> +ovn-sbctl dump-flows lr0 > lr0flows
> +AT_CAPTURE_FILE([lr0flows])
> +
> +dnl The priority-31 TTL expired flow for the l3dgw port must use explicit
> +dnl ip4.src assignment (the router port IP), not ip4.dst <-> ip4.src swap.
> +AT_CHECK([grep 'priority=31.*lr0-public.*ip4.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == 
> "lr0-public" && ip4 && ip4.src == 172.168.0.0/24 && ip.ttl == {0, 1} && 
> !ip.later_frag && is_chassis_resident("cr-lr0-public")), action=(icmp4 
> {eth.dst = eth.src; eth.src = 00:00:00:00:ff:02; icmp4.type = 11; /* Time 
> exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; 
> ip4.src = 172.168.0.10; ip.ttl = 254; outport = "lr0-public"; flags.loopback 
> = 1; output; };)
> +])
> +
> +dnl Non-l3dgw port should also use explicit assignment (unchanged behavior).
> +AT_CHECK([grep 'priority=31.*lr0-sw0.*ip4.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw0" 
> && ip4 && ip4.src == 10.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst = eth.src; eth.src = 00:00:00:00:ff:01; icmp4.type = 
> 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst 
> = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 254; outport = "lr0-sw0"; 
> flags.loopback = 1; output; };)
> +])
> +
> +dnl IPv6: l3dgw port must use explicit ip6.src assignment, not swap.
> +AT_CHECK([grep 'priority=31.*lr0-public.*ip6.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == 
> "lr0-public" && ip6 && ip6.src == 2001:db8:1::/64 && ip.ttl == {0, 1} && 
> !ip.later_frag && is_chassis_resident("cr-lr0-public")), action=(icmp6 
> {eth.dst = eth.src; eth.src = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = 
> 2001:db8:1::1; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 
> 0; /* TTL exceeded in transit */ outport = "lr0-public"; flags.loopback = 1; 
> output; };)
> +])
> +
> +dnl IPv6: non-l3dgw port (unchanged behavior).
> +AT_CHECK([grep 'priority=31.*lr0-sw0.*ip6.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw0" 
> && ip6 && ip6.src == 2001:db8::/64 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp6 {eth.dst = eth.src; eth.src = 00:00:00:00:ff:01; ip6.dst = 
> ip6.src; ip6.src = 2001:db8::1; ip.ttl = 254; icmp6.type = 3; /* Time 
> exceeded */ icmp6.code = 0; /* TTL exceeded in transit */ outport = 
> "lr0-sw0"; flags.loopback = 1; output; };)
> +])
> +
> +AT_CHECK([grep 'priority=30.*lr0-public.*ip4.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip4 && ip.ttl == {0, 1} && !ip.later_frag && 
> is_chassis_resident("cr-lr0-public")), action=(icmp4 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:ff:02; icmp4.type = 11; /* Time exceeded */ icmp4.code 
> = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 172.168.0.10; 
> ip.ttl = 254; outport = "lr0-public"; flags.loopback = 1; output; };)
> +])
> +
> +dnl Non-l3dgw port should also use explicit assignment (unchanged behavior).
> +AT_CHECK([grep 'priority=30.*lr0-sw0.*ip4.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:01; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 10.0.0.1; ip.ttl = 254; outport = "lr0-sw0"; flags.loopback = 1; output; };)
> +])
> +
> +dnl IPv6: l3dgw port must use explicit ip6.src assignment, not swap.
> +AT_CHECK([grep 'priority=30.*lr0-public.*ip6.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip6 && ip.ttl == {0, 1} && !ip.later_frag && 
> is_chassis_resident("cr-lr0-public")), action=(icmp6 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = 2001:db8:1::1; 
> ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL 
> exceeded in transit */ outport = "lr0-public"; flags.loopback = 1; output; };)
> +])
> +
> +dnl IPv6: non-l3dgw port (unchanged behavior).
> +AT_CHECK([grep 'priority=30.*lr0-sw0.*ip6.*ip.ttl' lr0flows | 
> ovn_strip_lflows], [0], [dnl
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = 
> 2001:db8::1; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 
> 0; /* TTL exceeded in transit */ outport = "lr0-sw0"; flags.loopback = 1; 
> output; };)
> +])
> +
> +OVN_CLEANUP_NORTHD
> +AT_CLEANUP
> +])
> +
>  OVN_FOR_EACH_NORTHD_NO_HV([
>  AT_SETUP([IP multicast flood without IGMP relay])
>  AT_KEYWORDS([mcast_relay])
> @@ -14634,15 +14701,15 @@ AT_CHECK([grep "lr_in_ip_input" lr0flows | 
> ovn_strip_lflows], [0], [dnl
>    table=??(lr_in_ip_input     ), priority=100  , match=(ip4.src_mcast 
> ||ip4.src == 255.255.255.255 || ip4.src == 127.0.0.0/8 || ip4.dst == 
> 127.0.0.0/8 || ip4.src == 0.0.0.0/8 || ip4.dst == 0.0.0.0/8), action=(drop;)
>    table=??(lr_in_ip_input     ), priority=120  , match=(inport == 
> "lr0-public" && ip4.src == 172.168.0.100), action=(next;)
>    table=??(lr_in_ip_input     ), priority=29   , match=(ip.ttl == {0, 1}), 
> action=(drop;)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 
> {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* 
> TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 172.168.0.10; ip.ttl 
> = 254; outport = "lr0-public"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 
> {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; 
> ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL 
> exceeded in transit */ outport = "lr0-public"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> 
> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded 
> in transit */ ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 254; outport = 
> "lr0-sw0"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> 
> eth.src; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 254; 
> icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in 
> transit */ outport = "lr0-sw0"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> 
> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded 
> in transit */ ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 254; outport = 
> "lr0-sw1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> 
> eth.src; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff03; ip.ttl = 254; 
> icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in 
> transit */ outport = "lr0-sw1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw0" 
> && ip4 && ip4.src == 10.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 10.0.0.1 ; ip.ttl = 254; outport = "lr0-sw0"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw1" 
> && ip4 && ip4.src == 20.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 20.0.0.1 ; ip.ttl = 254; outport = "lr0-sw1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , 
> match=(is_chassis_resident("cr-lr0-public") && inport == "lr0-public" && ip4 
> && ip4.src == 172.168.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst <-> ip4.src ; ip.ttl = 
> 254; outport = "lr0-public"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip4 && ip.ttl == {0, 1} && !ip.later_frag && 
> is_chassis_resident("cr-lr0-public")), action=(icmp4 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:ff:02; icmp4.type = 11; /* Time exceeded */ icmp4.code 
> = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 172.168.0.10; 
> ip.ttl = 254; outport = "lr0-public"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip6 && ip.ttl == {0, 1} && !ip.later_frag && 
> is_chassis_resident("cr-lr0-public")), action=(icmp6 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = 
> fe80::200:ff:fe00:ff02; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lr0-public"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:01; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 10.0.0.1; ip.ttl = 254; outport = "lr0-sw0"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = 
> fe80::200:ff:fe00:ff01; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lr0-sw0"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:03; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 20.0.0.1; ip.ttl = 254; outport = "lr0-sw1"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:03; ip6.dst = ip6.src; ip6.src = 
> fe80::200:ff:fe00:ff03; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lr0-sw1"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == 
> "lr0-public" && ip4 && ip4.src == 172.168.0.0/24 && ip.ttl == {0, 1} && 
> !ip.later_frag && is_chassis_resident("cr-lr0-public")), action=(icmp4 
> {eth.dst = eth.src; eth.src = 00:00:00:00:ff:02; icmp4.type = 11; /* Time 
> exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; 
> ip4.src = 172.168.0.10; ip.ttl = 254; outport = "lr0-public"; flags.loopback 
> = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw0" 
> && ip4 && ip4.src == 10.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst = eth.src; eth.src = 00:00:00:00:ff:01; icmp4.type = 
> 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst 
> = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 254; outport = "lr0-sw0"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw1" 
> && ip4 && ip4.src == 20.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst = eth.src; eth.src = 00:00:00:00:ff:03; icmp4.type = 
> 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst 
> = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 254; outport = "lr0-sw1"; 
> flags.loopback = 1; output; };)
>    table=??(lr_in_ip_input     ), priority=32   , match=(ip.ttl == {0, 1} && 
> !ip.later_frag && (ip4.mcast || ip6.mcast)), action=(drop;)
>    table=??(lr_in_ip_input     ), priority=50   , match=(eth.bcast), 
> action=(drop;)
>    table=??(lr_in_ip_input     ), priority=60   , match=(ip4.dst == 
> {10.0.0.1}), action=(drop;)
> @@ -14816,15 +14883,15 @@ AT_CHECK([grep "lr_in_ip_input" lr0flows | 
> ovn_strip_lflows], [0], [dnl
>    table=??(lr_in_ip_input     ), priority=100  , match=(ip4.src_mcast 
> ||ip4.src == 255.255.255.255 || ip4.src == 127.0.0.0/8 || ip4.dst == 
> 127.0.0.0/8 || ip4.src == 0.0.0.0/8 || ip4.dst == 0.0.0.0/8), action=(drop;)
>    table=??(lr_in_ip_input     ), priority=120  , match=(inport == 
> "lr0-public" && ip4.src == 172.168.0.100), action=(next;)
>    table=??(lr_in_ip_input     ), priority=29   , match=(ip.ttl == {0, 1}), 
> action=(drop;)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 
> {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* 
> TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 172.168.0.10; ip.ttl 
> = 254; outport = "lr0-public"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 
> {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; 
> ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL 
> exceeded in transit */ outport = "lr0-public"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> 
> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded 
> in transit */ ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 254; outport = 
> "lr0-sw0"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> 
> eth.src; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 254; 
> icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in 
> transit */ outport = "lr0-sw0"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> 
> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded 
> in transit */ ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 254; outport = 
> "lr0-sw1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> 
> eth.src; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff03; ip.ttl = 254; 
> icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in 
> transit */ outport = "lr0-sw1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw0" 
> && ip4 && ip4.src == 10.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 10.0.0.1 ; ip.ttl = 254; outport = "lr0-sw0"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw1" 
> && ip4 && ip4.src == 20.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 20.0.0.1 ; ip.ttl = 254; outport = "lr0-sw1"; flags.loopback = 1; output; };)
> -  table=??(lr_in_ip_input     ), priority=31   , 
> match=(is_chassis_resident("cr-lr0-public") && inport == "lr0-public" && ip4 
> && ip4.src == 172.168.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst <-> ip4.src ; ip.ttl = 
> 254; outport = "lr0-public"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip4 && ip.ttl == {0, 1} && !ip.later_frag && 
> is_chassis_resident("cr-lr0-public")), action=(icmp4 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:ff:02; icmp4.type = 11; /* Time exceeded */ icmp4.code 
> = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 172.168.0.10; 
> ip.ttl = 254; outport = "lr0-public"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == 
> "lr0-public" && ip6 && ip.ttl == {0, 1} && !ip.later_frag && 
> is_chassis_resident("cr-lr0-public")), action=(icmp6 {eth.dst = eth.src; 
> eth.src = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = 
> fe80::200:ff:fe00:ff02; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lr0-public"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:01; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 10.0.0.1; ip.ttl = 254; outport = "lr0-sw0"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw0" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = 
> fe80::200:ff:fe00:ff01; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lr0-sw0"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:03; icmp4.type = 11; /* Time exceeded */ 
> icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 
> 20.0.0.1; ip.ttl = 254; outport = "lr0-sw1"; flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=30   , match=(inport == "lr0-sw1" 
> && ip6 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst = 
> eth.src; eth.src = 00:00:00:00:ff:03; ip6.dst = ip6.src; ip6.src = 
> fe80::200:ff:fe00:ff03; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ 
> icmp6.code = 0; /* TTL exceeded in transit */ outport = "lr0-sw1"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == 
> "lr0-public" && ip4 && ip4.src == 172.168.0.0/24 && ip.ttl == {0, 1} && 
> !ip.later_frag && is_chassis_resident("cr-lr0-public")), action=(icmp4 
> {eth.dst = eth.src; eth.src = 00:00:00:00:ff:02; icmp4.type = 11; /* Time 
> exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; 
> ip4.src = 172.168.0.10; ip.ttl = 254; outport = "lr0-public"; flags.loopback 
> = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw0" 
> && ip4 && ip4.src == 10.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst = eth.src; eth.src = 00:00:00:00:ff:01; icmp4.type = 
> 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst 
> = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 254; outport = "lr0-sw0"; 
> flags.loopback = 1; output; };)
> +  table=??(lr_in_ip_input     ), priority=31   , match=(inport == "lr0-sw1" 
> && ip4 && ip4.src == 20.0.0.0/24 && ip.ttl == {0, 1} && !ip.later_frag), 
> action=(icmp4 {eth.dst = eth.src; eth.src = 00:00:00:00:ff:03; icmp4.type = 
> 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst 
> = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 254; outport = "lr0-sw1"; 
> flags.loopback = 1; output; };)
>    table=??(lr_in_ip_input     ), priority=32   , match=(ip.ttl == {0, 1} && 
> !ip.later_frag && (ip4.mcast || ip6.mcast)), action=(drop;)
>    table=??(lr_in_ip_input     ), priority=50   , match=(eth.bcast), 
> action=(drop;)
>    table=??(lr_in_ip_input     ), priority=60   , match=(ip4.dst == 
> {10.0.0.1}), action=(drop;)

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

Reply via email to