773311
From cfb0f49b644f2a253cc1365c219d1bb78c2cacac Mon Sep 17 00:00:00 2001
773311
From: Numan Siddique <numans@ovn.org>
773311
Date: Fri, 24 Apr 2020 12:19:09 +0530
773311
Subject: [PATCH] Fix ACL reject action for UDP packets.
773311
773311
The icmp packet generated by ovn-controller for reject ACL action
773311
for non TCP packets is not getting delivered to the sender of
773311
the original packet. This is because the icmp packets are skipped
773311
from out_pre_lb/out_pre_acl logical switch egress pipeline and this
773311
results in these icmp packets getting dropped in the ACL stage because
773311
of invalid ct flags. This patch fixes this issue by removing those logical
773311
flows. The IP checksum generated by ovn-controller is invalid. This patch
773311
fixes this issue as well.
773311
773311
Tested-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
773311
Signed-off-by: Numan Siddique <numans@ovn.org>
773311
773311
(cherry-picked from upstream commit f792b1a00b439a949e3b7aae4951f8513340c1a1)
773311
773311
Change-Id: I9837991cf0981f57dc92d1309f0f453c800d7937
773311
---
773311
 controller/pinctrl.c | 102 ++++++++++++++++++++++++++++---------------
773311
 northd/ovn-northd.c  |  22 +++++-----
773311
 tests/ovn.at         |  46 +++++++++----------
773311
 tests/system-ovn.at  |  95 ++++++++++++++++++++++++++++++++--------
773311
 4 files changed, 177 insertions(+), 88 deletions(-)
773311
773311
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
773311
index f0d63b9a6..9d5b7c3c0 100644
773311
--- a/controller/pinctrl.c
773311
+++ b/controller/pinctrl.c
773311
@@ -1465,7 +1465,7 @@ static void
773311
 pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
773311
                     struct dp_packet *pkt_in,
773311
                     const struct match *md, struct ofpbuf *userdata,
773311
-                    bool include_orig_ip_datagram)
773311
+                    bool set_icmp_code)
773311
 {
773311
     /* This action only works for IP packets, and the switch should only send
773311
      * us IP packets this way, but check here just to be sure. */
773311
@@ -1512,46 +1512,51 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
773311
         packet_set_ipv4(&packet, ip_flow->nw_src, ip_flow->nw_dst,
773311
                         ip_flow->nw_tos, 255);
773311
 
773311
+        uint8_t icmp_code =  1;
773311
+        if (set_icmp_code && in_ip->ip_proto == IPPROTO_UDP) {
773311
+            icmp_code = 3;
773311
+        }
773311
+
773311
         struct icmp_header *ih = dp_packet_put_zeros(&packet, sizeof *ih);
773311
         dp_packet_set_l4(&packet, ih);
773311
-        packet_set_icmp(&packet, ICMP4_DST_UNREACH, 1);
773311
-
773311
-        if (include_orig_ip_datagram) {
773311
-            /* RFC 1122: 3.2.2	MUST send at least the IP header and 8 bytes
773311
-             * of header. MAY send more.
773311
-             * RFC says return as much as we can without exceeding 576
773311
-             * bytes.
773311
-             * So, lets return as much as we can. */
773311
-
773311
-            /* Calculate available room to include the original IP + data. */
773311
-            nh = dp_packet_l3(&packet);
773311
-            uint16_t room = 576 - (sizeof *eh + ntohs(nh->ip_tot_len));
773311
-            if (in_ip_len > room) {
773311
-                in_ip_len = room;
773311
-            }
773311
-            dp_packet_put(&packet, in_ip, in_ip_len);
773311
-
773311
-            /* dp_packet_put may reallocate the buffer. Get the l3 and l4
773311
-             * header pointers again. */
773311
-            nh = dp_packet_l3(&packet);
773311
-            ih = dp_packet_l4(&packet);
773311
-            uint16_t ip_total_len = ntohs(nh->ip_tot_len) + in_ip_len;
773311
-            nh->ip_tot_len = htons(ip_total_len);
773311
-            ih->icmp_csum = 0;
773311
-            ih->icmp_csum = csum(ih, sizeof *ih + in_ip_len);
773311
-            nh->ip_csum = 0;
773311
-            nh->ip_csum = csum(nh, sizeof *nh);
773311
-        }
773311
+        packet_set_icmp(&packet, ICMP4_DST_UNREACH, icmp_code);
773311
+
773311
+        /* RFC 1122: 3.2.2	MUST send at least the IP header and 8 bytes
773311
+         * of header. MAY send more.
773311
+         * RFC says return as much as we can without exceeding 576
773311
+         * bytes.
773311
+         * So, lets return as much as we can. */
773311
+
773311
+        /* Calculate available room to include the original IP + data. */
773311
+        nh = dp_packet_l3(&packet);
773311
+        uint16_t room = 576 - (sizeof *eh + ntohs(nh->ip_tot_len));
773311
+        if (in_ip_len > room) {
773311
+            in_ip_len = room;
773311
+        }
773311
+        dp_packet_put(&packet, in_ip, in_ip_len);
773311
+
773311
+        /* dp_packet_put may reallocate the buffer. Get the l3 and l4
773311
+            * header pointers again. */
773311
+        nh = dp_packet_l3(&packet);
773311
+        ih = dp_packet_l4(&packet);
773311
+        uint16_t ip_total_len = ntohs(nh->ip_tot_len) + in_ip_len;
773311
+        nh->ip_tot_len = htons(ip_total_len);
773311
+        ih->icmp_csum = 0;
773311
+        ih->icmp_csum = csum(ih, sizeof *ih + in_ip_len);
773311
+        nh->ip_csum = 0;
773311
+        nh->ip_csum = csum(nh, sizeof *nh);
773311
+
773311
     } else {
773311
         struct ip6_hdr *nh = dp_packet_put_zeros(&packet, sizeof *nh);
773311
         struct icmp6_data_header *ih;
773311
         uint32_t icmpv6_csum;
773311
+        struct ip6_hdr *in_ip = dp_packet_l3(pkt_in);
773311
 
773311
         eh->eth_type = htons(ETH_TYPE_IPV6);
773311
         dp_packet_set_l3(&packet, nh);
773311
         nh->ip6_vfc = 0x60;
773311
         nh->ip6_nxt = IPPROTO_ICMPV6;
773311
-        nh->ip6_plen = htons(sizeof(*nh) + ICMP6_DATA_HEADER_LEN);
773311
+        nh->ip6_plen = htons(ICMP6_DATA_HEADER_LEN);
773311
         packet_set_ipv6(&packet, &ip_flow->ipv6_src, &ip_flow->ipv6_dst,
773311
                         ip_flow->nw_tos, ip_flow->ipv6_label, 255);
773311
 
773311
@@ -1559,15 +1564,42 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
773311
         dp_packet_set_l4(&packet, ih);
773311
         ih->icmp6_base.icmp6_type = ICMP6_DST_UNREACH;
773311
         ih->icmp6_base.icmp6_code = 1;
773311
+
773311
+        if (set_icmp_code && in_ip->ip6_nxt == IPPROTO_UDP) {
773311
+            ih->icmp6_base.icmp6_code = ICMP6_DST_UNREACH_NOPORT;
773311
+        }
773311
         ih->icmp6_base.icmp6_cksum = 0;
773311
 
773311
-        uint8_t *data = dp_packet_put_zeros(&packet, sizeof *nh);
773311
-        memcpy(data, dp_packet_l3(pkt_in), sizeof(*nh));
773311
+        nh = dp_packet_l3(&packet);
773311
+
773311
+        /* RFC 4443: 3.1.
773311
+         *
773311
+         * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
773311
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
773311
+         * |     Type      |     Code      |          Checksum             |
773311
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
773311
+         * |                             Unused                            |
773311
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
773311
+         * |                    As much of invoking packet                 |
773311
+         * +                as possible without the ICMPv6 packet          +
773311
+         * |                exceeding the minimum IPv6 MTU [IPv6]          |
773311
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
773311
+         */
773311
+
773311
+        uint16_t room = 1280 - (sizeof *eh + sizeof *nh +
773311
+                                ICMP6_DATA_HEADER_LEN);
773311
+        uint16_t in_ip_len = (uint16_t) sizeof *in_ip + ntohs(in_ip->ip6_plen);
773311
+        if (in_ip_len > room) {
773311
+            in_ip_len = room;
773311
+        }
773311
+
773311
+        dp_packet_put(&packet, in_ip, in_ip_len);
773311
+        nh->ip6_plen = htons(ICMP6_DATA_HEADER_LEN + in_ip_len);
773311
 
773311
         icmpv6_csum = packet_csum_pseudoheader6(dp_packet_l3(&packet));
773311
         ih->icmp6_base.icmp6_cksum = csum_finish(
773311
             csum_continue(icmpv6_csum, ih,
773311
-                          sizeof(*nh) + ICMP6_DATA_HEADER_LEN));
773311
+                          in_ip_len + ICMP6_DATA_HEADER_LEN));
773311
     }
773311
 
773311
     if (ip_flow->vlans[0].tci & htons(VLAN_CFI)) {
773311
@@ -2658,12 +2690,12 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg)
773311
 
773311
     case ACTION_OPCODE_ICMP:
773311
         pinctrl_handle_icmp(swconn, &headers, &packet, &pin.flow_metadata,
773311
-                            &userdata, false);
773311
+                            &userdata, true);
773311
         break;
773311
 
773311
     case ACTION_OPCODE_ICMP4_ERROR:
773311
         pinctrl_handle_icmp(swconn, &headers, &packet, &pin.flow_metadata,
773311
-                            &userdata, true);
773311
+                            &userdata, false);
773311
         break;
773311
 
773311
     case ACTION_OPCODE_TCP_RESET:
773311
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
773311
index 4efe4a0c3..ec77ae1a8 100644
773311
--- a/northd/ovn-northd.c
773311
+++ b/northd/ovn-northd.c
773311
@@ -4736,12 +4736,10 @@ build_pre_acls(struct ovn_datapath *od, struct hmap *lflows)
773311
          * Not to do conntrack on ND and ICMP destination
773311
          * unreachable packets. */
773311
         ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110,
773311
-                      "nd || nd_rs || nd_ra || icmp4.type == 3 || "
773311
-                      "icmp6.type == 1 || "
773311
+                      "nd || nd_rs || nd_ra || "
773311
                       "(udp && udp.src == 546 && udp.dst == 547)", "next;");
773311
         ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110,
773311
-                      "nd || nd_rs || nd_ra || icmp4.type == 3 || "
773311
-                      "icmp6.type == 1 || "
773311
+                      "nd || nd_rs || nd_ra || "
773311
                       "(udp && udp.src == 546 && udp.dst == 547)", "next;");
773311
 
773311
         /* Ingress and Egress Pre-ACL Table (Priority 100).
773311
@@ -4853,12 +4851,10 @@ build_pre_lb(struct ovn_datapath *od, struct hmap *lflows,
773311
 {
773311
     /* Do not send ND packets to conntrack */
773311
     ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_LB, 110,
773311
-                  "nd || nd_rs || nd_ra || icmp4.type == 3 ||"
773311
-                  "icmp6.type == 1",
773311
+                  "nd || nd_rs || nd_ra",
773311
                   "next;");
773311
     ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_LB, 110,
773311
-                  "nd || nd_rs || nd_ra || icmp4.type == 3 ||"
773311
-                  "icmp6.type == 1",
773311
+                  "nd || nd_rs || nd_ra",
773311
                   "next;");
773311
 
773311
     /* Do not send service monitor packets to conntrack. */
773311
@@ -5037,9 +5033,10 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
773311
         ds_put_format(&actions, "%s ", extra_actions->string);
773311
     }
773311
     ds_put_format(&actions, "reg0 = 0; "
773311
-                  "eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
773311
-                  "icmp4 { outport <-> inport; %s };",
773311
-                  ingress ? "output;" : "next(pipeline=ingress,table=0);");
773311
+                  "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
773311
+                  "outport <-> inport; %s };",
773311
+                  ingress ? "next(pipeline=egress,table=5);"
773311
+                          : "next(pipeline=ingress,table=19);");
773311
     ovn_lflow_add_with_hint(lflows, od, stage,
773311
                             acl->priority + OVN_ACL_PRI_OFFSET,
773311
                             ds_cstr(&match), ds_cstr(&actions), stage_hint);
773311
@@ -5056,7 +5053,8 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
773311
     ds_put_format(&actions, "reg0 = 0; icmp6 { "
773311
                   "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
773311
                   "outport <-> inport; %s };",
773311
-                  ingress ? "output;" : "next(pipeline=ingress,table=0);");
773311
+                  ingress ? "next(pipeline=egress,table=5);"
773311
+                          : "next(pipeline=ingress,table=19);");
773311
     ovn_lflow_add_with_hint(lflows, od, stage,
773311
                             acl->priority + OVN_ACL_PRI_OFFSET,
773311
                             ds_cstr(&match), ds_cstr(&actions), stage_hint);
773311
diff --git a/tests/ovn.at b/tests/ovn.at
773311
index defe00a40..35415f2b6 100644
773311
--- a/tests/ovn.at
773311
+++ b/tests/ovn.at
773311
@@ -11737,13 +11737,13 @@ test_ip_packet() {
773311
 
773311
     local ip_ttl=ff
773311
     local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
773311
-
773311
+    local orig_pkt_in_reply=4500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
773311
     local reply_icmp_ttl=ff
773311
     local icmp_type_code_response=0301
773311
     local icmp_data=00000000
773311
     local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
773311
-    local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
773311
-    echo $reply >> vif$inport.expected
773311
+    local reply=${eth_src}${eth_dst}08004500003000004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
773311
+    echo $reply$orig_pkt_in_reply >> vif$inport.expected
773311
 
773311
     as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
773311
 }
773311
@@ -11760,7 +11760,7 @@ test_ipv6_packet() {
773311
     local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
773311
     local packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
773311
 
773311
-    local reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr}
773311
+    local reply=${eth_src}${eth_dst}86dd6000000000383aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr}0000000000000000
773311
     echo $reply >> vif$inport.expected
773311
 
773311
     as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
773311
@@ -11838,11 +11838,11 @@ ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p21\"" reject
773311
 # Allow some time for ovn-northd and ovn-controller to catch up.
773311
 ovn-nbctl --timeout=3 --wait=hv sync
773311
 
773311
-test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
773311
-test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
773311
-test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
773311
+test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 f85b f576
773311
+test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 f85b f576
773311
+test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 f850 f56b
773311
 
773311
-test_ipv6_packet 11 1 000000000011 000000000021 fe80000000000000020001fffe000001 fe80000000000000020001fffe000002 6183
773311
+test_ipv6_packet 11 1 000000000011 000000000021 fe80000000000000020001fffe000001 fe80000000000000020001fffe000002 617b
773311
 
773311
 test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 b85f 70e4
773311
 test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 b85f 70e4
773311
@@ -12795,13 +12795,13 @@ test_ip_packet() {
773311
 
773311
     local ip_ttl=01
773311
     local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
773311
-
773311
+    local orig_pkt_in_reply=4500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
773311
     local reply_icmp_ttl=fe
773311
     local icmp_type_code_response=0b00
773311
     local icmp_data=00000000
773311
     local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
773311
-    local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
773311
-    echo $reply >> vif$inport.expected
773311
+    local reply=${eth_src}${eth_dst}08004500003000004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
773311
+    echo $reply$orig_pkt_in_reply >> vif$inport.expected
773311
 
773311
     as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
773311
 }
773311
@@ -12819,7 +12819,7 @@ test_ip6_packet() {
773311
     local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
773311
     local packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a
773311
 
773311
-    local reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}
773311
+    local reply=${eth_src}${eth_dst}86dd6000000000453afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a
773311
     echo $reply >> vif$inport.expected
773311
 
773311
     as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
773311
@@ -12861,8 +12861,8 @@ OVN_POPULATE_ARP
773311
 # allow some time for ovn-northd and ovn-controller to catch up.
773311
 ovn-nbctl --wait=hv sync
773311
 
773311
-test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae f4ff
773311
-test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000200000000000000000011 20010db8000100000000000000000001 d461
773311
+test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 f87c ea96
773311
+test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000200000000000000000011 20010db8000100000000000000000001 1c22
773311
 OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
773311
 
773311
 OVN_CLEANUP([hv1], [hv2])
773311
@@ -12891,12 +12891,12 @@ test_ip_packet() {
773311
 
773311
     local ip_ttl=ff
773311
     local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router}
773311
-
773311
+    local orig_pkt_in_reply=4500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router}
773311
     local reply_icmp_ttl=fe
773311
     local icmp_data=00000000
773311
     local reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
773311
-    local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
773311
-    echo $reply >> vif$inport.expected
773311
+    local reply=${eth_src}${eth_dst}08004500003000004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
773311
+    echo $reply$orig_pkt_in_reply >> vif$inport.expected
773311
 
773311
     as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
773311
 }
773311
@@ -12962,7 +12962,9 @@ test_ip6_packet() {
773311
     local ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
773311
     local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
773311
 
773311
-    local reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr}
773311
+    local reply_ip_len=`expr 48 + ${#data} / 2`
773311
+    reply_ip_len=$(printf "%x" $reply_ip_len)
773311
+    local reply=${eth_src}${eth_dst}86dd6000000000${reply_ip_len}3afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr}${data}
773311
     echo $reply >> vif$inport.expected
773311
 
773311
     as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
773311
@@ -13004,13 +13006,13 @@ OVN_POPULATE_ARP
773311
 # allow some time for ovn-northd and ovn-controller to catch up.
773311
 ovn-nbctl --wait=hv sync
773311
 
773311
-test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
773311
-test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
773311
-test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000100000000000000000001 11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
773311
+test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 11 0000 f87c f485 0303
773311
+test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 84 0000 f87c f413 0302
773311
+test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000100000000000000000001 11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 1d31
773311
 OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
773311
 
773311
 test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 b680 6e05
773311
-test_ip6_packet 2 2 000000000002 00000000ff02 20010db8000200000000000000000011 20010db8000200000000000000000001 84 0004 01020304 0103 627e
773311
+test_ip6_packet 2 2 000000000002 00000000ff02 20010db8000200000000000000000011 20010db8000200000000000000000001 84 0004 01020304 0103 5e74
773311
 test_tcp6_packet 2 2 000000000002 00000000ff02 20010db8000200000000000000000011 20010db8000200000000000000000001 8b40 3039 0000 98cd
773311
 OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
773311
 
773311
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
773311
index fa3b83cb1..117f1e835 100644
773311
--- a/tests/system-ovn.at
773311
+++ b/tests/system-ovn.at
773311
@@ -3697,7 +3697,7 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
773311
 AT_CLEANUP
773311
 
773311
 
773311
-AT_SETUP([ovn -- ACL reject - TCP reset])
773311
+AT_SETUP([ovn -- ACL reject])
773311
 AT_SKIP_IF([test $HAVE_NC = no])
773311
 AT_KEYWORDS([lb])
773311
 
773311
@@ -3736,13 +3736,14 @@ ovn-nbctl acl-add pg0_drop from-lport 1001 "inport == @pg0_drop && ip" drop
773311
 ovn-nbctl acl-add pg0_drop to-lport 1001 "outport == @pg0_drop && ip" drop
773311
 
773311
 ovn-nbctl pg-add pg0 sw0-p1-rej sw0-p2-rej
773311
-ovn-nbctl acl-add pg0 from-lport 1002 "inport == @pg0 && ip4" allow-related
773311
+ovn-nbctl acl-add pg0 from-lport 1002 "inport == @pg0 && ip" allow-related
773311
 ovn-nbctl --log acl-add pg0 from-lport 1004 "inport == @pg0 && ip && tcp && tcp.dst == 80" reject
773311
+ovn-nbctl --log acl-add pg0 from-lport 1004 "inport == @pg0 && ip && udp && udp.dst == 90" reject
773311
 
773311
-ovn-nbctl acl-add pg0 to-lport 1002 "outport == @pg0 && ip4 && ip4.src == 0.0.0.0/0 && icmp4" allow-related
773311
 ovn-nbctl acl-add pg0 to-lport 1002 "outport == @pg0 && ip4 && ip4.src == 0.0.0.0/0 && tcp && tcp.dst == 82" allow-related
773311
 ovn-nbctl acl-add pg0 to-lport 1002 "outport == @pg0 && ip4 && ip4.src == 0.0.0.0/0 && udp && udp.dst == 82" allow-related
773311
 ovn-nbctl --log acl-add pg0 to-lport 1004 "inport == @pg0 && ip && tcp && tcp.dst == 84" reject
773311
+ovn-nbctl --log acl-add pg0 to-lport 1004 "inport == @pg0 && ip && udp && udp.dst == 94" reject
773311
 
773311
 OVN_POPULATE_ARP
773311
 ovn-nbctl --wait=hv sync
773311
@@ -3758,33 +3759,38 @@ ADD_VETH(sw0-p2-rej, sw0-p2-rej, br-int, "10.0.0.4/24", "50:54:00:00:00:04", \
773311
 NS_CHECK_EXEC([sw0-p1-rej], [ip a a aef0::3/64 dev sw0-p1-rej], [0])
773311
 NS_CHECK_EXEC([sw0-p2-rej], [ip a a aef0::4/64 dev sw0-p2-rej], [0])
773311
 
773311
-# Capture packets in sw0-p1-rej.
773311
-NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -n -c 2 -i sw0-p1-rej tcp port 80 > sw0-p1-rej-ip4.pcap &], [0])
773311
 sleep 1
773311
 
773311
-NS_CHECK_EXEC([sw0-p1-rej], [nc 10.0.0.4 80], [1], [],
773311
-[dnl
773311
-Ncat: Connection refused.
773311
-])
773311
+# Capture packets in sw0-p1-rej.
773311
+NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -n -c 4 -i sw0-p1-rej tcp > sw0-p1-rej-ip4.pcap &], [0])
773311
+
773311
+sleep 1
773311
 
773311
 OVS_WAIT_UNTIL([
773311
-    total=`cat sw0-p1-rej-ip4.pcap |  wc -l`
773311
-    echo "total = $total"
773311
-    test "${total}" = "2"
773311
+    ip netns exec sw0-p1-rej nc  10.0.0.4 80 2> r
773311
+    res=$(cat r)
773311
+    test "$res" = "Ncat: Connection refused."
773311
 ])
773311
 
773311
 # Now send traffic to port 84
773311
-NS_CHECK_EXEC([sw0-p1-rej], [nc 10.0.0.4 84], [1], [],
773311
-[dnl
773311
-Ncat: Connection refused.
773311
+OVS_WAIT_UNTIL([
773311
+    ip netns exec sw0-p1-rej nc  10.0.0.4 84 2> r
773311
+    res=$(cat r)
773311
+    test "$res" = "Ncat: Connection refused."
773311
 ])
773311
 
773311
-AT_CHECK([
773311
+OVS_WAIT_UNTIL([
773311
     n_pkt=$(ovs-ofctl dump-flows br-int table=44 | grep -v n_packets=0 | \
773311
 grep controller | grep tp_dst=84 -c)
773311
     test $n_pkt -eq 1
773311
 ])
773311
 
773311
+OVS_WAIT_UNTIL([
773311
+    total=`cat sw0-p1-rej-ip4.pcap |  wc -l`
773311
+    echo "total = $total"
773311
+    test "${total}" = "4"
773311
+])
773311
+
773311
 # Without this sleep, test case fails intermittently.
773311
 sleep 3
773311
 
773311
@@ -3792,17 +3798,68 @@ NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -n -c 2 -i sw0-p2-rej tcp port 80 > sw0-p2-
773311
 
773311
 sleep 1
773311
 
773311
-NS_CHECK_EXEC([sw0-p2-rej], [nc -6 aef0::3 80], [1], [],
773311
-[dnl
773311
-Ncat: Connection refused.
773311
+OVS_WAIT_UNTIL([
773311
+    ip netns exec sw0-p2-rej nc -6 aef0::3 80 2> r
773311
+    res=$(cat r)
773311
+    test "$res" = "Ncat: Connection refused."
773311
 ])
773311
 
773311
+
773311
 OVS_WAIT_UNTIL([
773311
     total=`cat sw0-p2-rej-ip6.pcap |  wc -l`
773311
     echo "total = $total"
773311
     test "${total}" = "2"
773311
 ])
773311
 
773311
+# Now test for IPv4 UDP.
773311
+NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -n -c 1 -i sw0-p1-rej udp port 90 > sw0-p1-rej-udp.pcap &], [0])
773311
+NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -n -c 1 -i sw0-p1-rej icmp > sw0-p1-rej-icmp.pcap &], [0])
773311
+
773311
+echo "foo" > foo
773311
+OVS_WAIT_UNTIL([
773311
+    ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo
773311
+    c=$(cat sw0-p1-rej-icmp.pcap | grep \
773311
+"10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port dnsix unreachable" | uniq | wc -l)
773311
+    test $c -eq 1
773311
+])
773311
+
773311
+rm -f *.pcap
773311
+
773311
+NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -n -c 1 -i sw0-p1-rej udp port 94 > sw0-p1-rej-udp.pcap &], [0])
773311
+NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -n -c 1 -i sw0-p1-rej icmp > sw0-p1-rej-icmp.pcap &], [0])
773311
+
773311
+OVS_WAIT_UNTIL([
773311
+    ip netns exec sw0-p1-rej nc -u 10.0.0.4 94 < foo
773311
+    c=$(cat sw0-p1-rej-icmp.pcap | grep \
773311
+"10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port objcall unreachable" | uniq | wc -l)
773311
+    test $c -eq 1
773311
+])
773311
+
773311
+# Now test for IPv6 UDP.
773311
+NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -n -c 1 -i sw0-p2-rej udp port 90 > sw0-p2-rej-ip6-udp.pcap &], [0])
773311
+NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -n -c 1 -i sw0-p2-rej icmp6 > sw0-p2-rej-icmp6.pcap &], [0])
773311
+
773311
+OVS_WAIT_UNTIL([
773311
+    ip netns exec sw0-p2-rej nc -u -6 aef0::3 90 < foo
773311
+    c=$(cat sw0-p2-rej-icmp6.pcap | grep \
773311
+"IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
773311
+aef0::3 udp port dnsix" | uniq | wc -l)
773311
+    test $c -eq 1
773311
+])
773311
+
773311
+rm -f *.pcap
773311
+
773311
+NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -n -c 1 -i sw0-p2-rej udp port 94 > sw0-p2-rej-ip6-udp.pcap &], [0])
773311
+NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -n -c 1 -i sw0-p2-rej icmp6 > sw0-p2-rej-icmp6.pcap &], [0])
773311
+
773311
+OVS_WAIT_UNTIL([
773311
+    ip netns exec sw0-p2-rej nc -u -6 aef0::3 94 < foo
773311
+    c=$(cat sw0-p2-rej-icmp6.pcap | grep \
773311
+"IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
773311
+aef0::3 udp port objcall" | uniq | wc -l)
773311
+    test $c -eq 1
773311
+])
773311
+
773311
 OVS_APP_EXIT_AND_WAIT([ovn-controller])
773311
 
773311
 as ovn-sb
773311
-- 
773311
2.26.2
773311