[ovs-dev] [PATCH ovn v5 5/7] northd: Make use of new hairpin actions.

numans at ovn.org numans at ovn.org
Tue Nov 17 14:28:48 UTC 2020


From: Numan Siddique <numans at ovn.org>

This patch makes use of the new hairpin OVN actions - chk_lb_hairpin, chk_lb_hairpin_reply
and ct_snat_to_vip.

Suppose there are 'm' load balancers associated to a logical switch and each load balancer
has 'n' VIPs and each VIP has 'p' backends then ovn-northd adds (m * ((n * p) + n))
hairpin logical flows. After this patch, ovn-northd adds just 5 hairpin logical flows.

With this patch number of hairpin related OF flows on a chassis are almost the same as before,
but in a large scale deployment, this reduces memory consumption and load on ovn-northd and
SB DB ovsdb-servers.

Signed-off-by: Numan Siddique <numans at ovn.org>
---
 northd/ovn-northd.8.xml |  65 +++++++++++-----
 northd/ovn-northd.c     | 160 +++++++++++++---------------------------
 tests/ovn-northd.at     |  28 +++----
 tests/ovn.at            |   2 +-
 4 files changed, 116 insertions(+), 139 deletions(-)

diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index b37cecd381..8c0a4a98f5 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -718,24 +718,55 @@
     <h3>Ingress Table 12: Pre-Hairpin</h3>
     <ul>
       <li>
-        For all configured load balancer VIPs a priority-2 flow that
-        matches on traffic that needs to be hairpinned, i.e., after load
-        balancing the destination IP matches the source IP, which sets
-        <code>reg0[6] = 1 </code> and executes <code>ct_snat(VIP)</code>
-        to force replies to these packets to come back through OVN.
+        If the logical switch has load balancer(s) configured, then a
+        priorirty-100 flow is added with the match
+        <code>ip && ct.trk&& ct.dnat</code> to check if the
+        packet needs to be hairpinned ( if after load balancing the destination
+        IP matches the source IP) or not by executing the action
+        <code>reg0[6] = chk_lb_hairpin();</code> and advances the packet to
+        the next table.
+      </li>
+
+      <li>
+        If the logical switch has load balancer(s) configured, then a
+        priorirty-90 flow is added with the match <code>ip</code> to check if
+        the packet is a reply for a hairpinned connection or not by executing
+        the action <code>reg0[6] = chk_lb_hairpin_reply();</code> and advances
+        the packet to the next table.
       </li>
+
       <li>
-        For all configured load balancer VIPs a priority-1 flow that
-        matches on replies to hairpinned traffic, i.e., destination IP is VIP,
-        source IP is the backend IP and source L4 port is backend port, which
-        sets <code>reg0[6] = 1 </code> and executes <code>ct_snat;</code>.
+        A priority-0 flow that simply moves traffic to the next table.
       </li>
+    </ul>
+
+    <h3>Ingress Table 13: Nat-Hairpin</h3>
+    <ul>
+      <li>
+         If the logical switch has load balancer(s) configured, then a
+         priorirty-100 flow is added with the match
+         <code>ip && (ct.new || ct.est) && ct.trk &&
+         ct.dnat && reg0[6] == 1</code> which hairpins the traffic by
+         NATting source IP to the load balancer VIP by executing the action
+         <code>ct_snat_to_vip</code> and advances the packet to the next table.
+      </li>
+
+      <li>
+         If the logical switch has load balancer(s) configured, then a
+         priorirty-90 flow is added with the match
+         <code>ip && reg0[6] == 1</code> which matches on the replies
+         of hairpinned traffic ( i.e., destination IP is VIP,
+         source IP is the backend IP and source L4 port is backend port for L4
+         load balancers) and executes <code>ct_snat</code> and advances the
+         packet to the next table.
+      </li>
+
       <li>
         A priority-0 flow that simply moves traffic to the next table.
       </li>
     </ul>
 
-    <h3>Ingress Table 13: Hairpin</h3>
+    <h3>Ingress Table 14: Hairpin</h3>
     <ul>
       <li>
         A priority-1 flow that hairpins traffic matched by non-default
@@ -748,7 +779,7 @@
       </li>
     </ul>
 
-    <h3>Ingress Table 14: ARP/ND responder</h3>
+    <h3>Ingress Table 15: ARP/ND responder</h3>
 
     <p>
       This table implements ARP/ND responder in a logical switch for known
@@ -1038,7 +1069,7 @@ output;
       </li>
     </ul>
 
-    <h3>Ingress Table 15: DHCP option processing</h3>
+    <h3>Ingress Table 16: DHCP option processing</h3>
 
     <p>
       This table adds the DHCPv4 options to a DHCPv4 packet from the
@@ -1099,7 +1130,7 @@ next;
       </li>
     </ul>
 
-    <h3>Ingress Table 16: DHCP responses</h3>
+    <h3>Ingress Table 17: DHCP responses</h3>
 
     <p>
       This table implements DHCP responder for the DHCP replies generated by
@@ -1180,7 +1211,7 @@ output;
       </li>
     </ul>
 
-    <h3>Ingress Table 17 DNS Lookup</h3>
+    <h3>Ingress Table 18 DNS Lookup</h3>
 
     <p>
       This table looks up and resolves the DNS names to the corresponding
@@ -1209,7 +1240,7 @@ reg0[4] = dns_lookup(); next;
       </li>
     </ul>
 
-    <h3>Ingress Table 18 DNS Responses</h3>
+    <h3>Ingress Table 19 DNS Responses</h3>
 
     <p>
       This table implements DNS responder for the DNS replies generated by
@@ -1244,7 +1275,7 @@ output;
       </li>
     </ul>
 
-    <h3>Ingress table 19 External ports</h3>
+    <h3>Ingress table 20 External ports</h3>
 
     <p>
       Traffic from the <code>external</code> logical ports enter the ingress
@@ -1287,7 +1318,7 @@ output;
       </li>
     </ul>
 
-    <h3>Ingress Table 20 Destination Lookup</h3>
+    <h3>Ingress Table 21 Destination Lookup</h3>
 
     <p>
       This table implements switching behavior.  It contains these logical
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 2445c763e2..b5f7da8bd7 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -150,14 +150,15 @@ enum ovn_stage {
     PIPELINE_STAGE(SWITCH, IN,  LB,            10, "ls_in_lb")            \
     PIPELINE_STAGE(SWITCH, IN,  STATEFUL,      11, "ls_in_stateful")      \
     PIPELINE_STAGE(SWITCH, IN,  PRE_HAIRPIN,   12, "ls_in_pre_hairpin")   \
-    PIPELINE_STAGE(SWITCH, IN,  HAIRPIN,       13, "ls_in_hairpin")       \
-    PIPELINE_STAGE(SWITCH, IN,  ARP_ND_RSP,    14, "ls_in_arp_rsp")       \
-    PIPELINE_STAGE(SWITCH, IN,  DHCP_OPTIONS,  15, "ls_in_dhcp_options")  \
-    PIPELINE_STAGE(SWITCH, IN,  DHCP_RESPONSE, 16, "ls_in_dhcp_response") \
-    PIPELINE_STAGE(SWITCH, IN,  DNS_LOOKUP,    17, "ls_in_dns_lookup")    \
-    PIPELINE_STAGE(SWITCH, IN,  DNS_RESPONSE,  18, "ls_in_dns_response")  \
-    PIPELINE_STAGE(SWITCH, IN,  EXTERNAL_PORT, 19, "ls_in_external_port") \
-    PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,       20, "ls_in_l2_lkup")       \
+    PIPELINE_STAGE(SWITCH, IN,  NAT_HAIRPIN,   13, "ls_in_nat_hairpin")       \
+    PIPELINE_STAGE(SWITCH, IN,  HAIRPIN,       14, "ls_in_hairpin")       \
+    PIPELINE_STAGE(SWITCH, IN,  ARP_ND_RSP,    15, "ls_in_arp_rsp")       \
+    PIPELINE_STAGE(SWITCH, IN,  DHCP_OPTIONS,  16, "ls_in_dhcp_options")  \
+    PIPELINE_STAGE(SWITCH, IN,  DHCP_RESPONSE, 17, "ls_in_dhcp_response") \
+    PIPELINE_STAGE(SWITCH, IN,  DNS_LOOKUP,    18, "ls_in_dns_lookup")    \
+    PIPELINE_STAGE(SWITCH, IN,  DNS_RESPONSE,  19, "ls_in_dns_response")  \
+    PIPELINE_STAGE(SWITCH, IN,  EXTERNAL_PORT, 20, "ls_in_external_port") \
+    PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,       21, "ls_in_l2_lkup")       \
                                                                           \
     /* Logical switch egress stages. */                                   \
     PIPELINE_STAGE(SWITCH, OUT, PRE_LB,       0, "ls_out_pre_lb")         \
@@ -5827,85 +5828,6 @@ build_lb(struct ovn_datapath *od, struct hmap *lflows)
     }
 }
 
-static void
-build_lb_hairpin_rules(struct ovn_datapath *od, struct hmap *lflows,
-                       struct ovn_northd_lb *lb,
-                       struct ovn_lb_vip *lb_vip,
-                       const char *ip_match, const char *proto)
-{
-    if (lb_vip->n_backends == 0) {
-        return;
-    }
-
-    struct ds action = DS_EMPTY_INITIALIZER;
-    struct ds match_initiator = DS_EMPTY_INITIALIZER;
-    struct ds match_reply = DS_EMPTY_INITIALIZER;
-    struct ds proto_match = DS_EMPTY_INITIALIZER;
-
-    /* Ingress Pre-Hairpin table.
-     * - Priority 2: SNAT load balanced traffic that needs to be hairpinned:
-     *   - Both SRC and DST IP match backend->ip and destination port
-     *     matches backend->port.
-     * - Priority 1: unSNAT replies to hairpinned load balanced traffic.
-     *   - SRC IP matches backend->ip, DST IP matches LB VIP and source port
-     *     matches backend->port.
-     */
-    ds_put_char(&match_reply, '(');
-    for (size_t i = 0; i < lb_vip->n_backends; i++) {
-        struct ovn_lb_backend *backend = &lb_vip->backends[i];
-
-        /* Packets that after load balancing have equal source and
-         * destination IPs should be hairpinned.
-         */
-        if (lb_vip->vip_port) {
-            ds_put_format(&proto_match, " && %s.dst == %"PRIu16,
-                          proto, backend->port);
-        }
-        ds_put_format(&match_initiator, "(%s.src == %s && %s.dst == %s%s)",
-                      ip_match, backend->ip_str, ip_match, backend->ip_str,
-                      ds_cstr(&proto_match));
-
-        /* Replies to hairpinned traffic are originated by backend->ip:port. */
-        ds_clear(&proto_match);
-        if (lb_vip->vip_port) {
-            ds_put_format(&proto_match, " && %s.src == %"PRIu16, proto,
-                          backend->port);
-        }
-        ds_put_format(&match_reply, "(%s.src == %s%s)",
-                      ip_match, backend->ip_str, ds_cstr(&proto_match));
-        ds_clear(&proto_match);
-
-        if (i < lb_vip->n_backends - 1) {
-            ds_put_cstr(&match_initiator, " || ");
-            ds_put_cstr(&match_reply, " || ");
-        }
-    }
-    ds_put_char(&match_reply, ')');
-
-    /* SNAT hairpinned initiator traffic so that the reply traffic is
-     * also directed through OVN.
-     */
-    ds_put_format(&action, REGBIT_HAIRPIN " = 1; ct_snat(%s);",
-                  lb_vip->vip_str);
-    ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 2,
-                            ds_cstr(&match_initiator), ds_cstr(&action),
-                            &lb->nlb->header_);
-
-    /* Replies to hairpinned traffic are destined to the LB VIP. */
-    ds_put_format(&match_reply, " && %s.dst == %s", ip_match, lb_vip->vip_str);
-
-    /* UNSNAT replies for hairpinned traffic. */
-    ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 1,
-                            ds_cstr(&match_reply),
-                            REGBIT_HAIRPIN " = 1; ct_snat;",
-                            &lb->nlb->header_);
-
-    ds_destroy(&action);
-    ds_destroy(&match_initiator);
-    ds_destroy(&match_reply);
-    ds_destroy(&proto_match);
-}
-
 static void
 build_lb_rules(struct ovn_datapath *od, struct hmap *lflows,
                struct ovn_northd_lb *lb)
@@ -5954,12 +5876,6 @@ build_lb_rules(struct ovn_datapath *od, struct hmap *lflows,
 
         ds_destroy(&match);
         ds_destroy(&action);
-
-        /* Also install flows that allow hairpinning of traffic (i.e., if
-         * a load balancer VIP is DNAT-ed to a backend that happens to be
-         * the source of the traffic).
-         */
-        build_lb_hairpin_rules(od, lflows, lb, lb_vip, ip_match, proto);
     }
 }
 
@@ -6006,24 +5922,53 @@ build_stateful(struct ovn_datapath *od, struct hmap *lflows, struct hmap *lbs)
         ovs_assert(lb);
         build_lb_rules(od, lflows, lb);
     }
+}
 
-    /* Ingress Pre-Hairpin table (Priority 0). Packets that don't need
-     * hairpinning should continue processing.
+static void
+build_lb_hairpin(struct ovn_datapath *od, struct hmap *lflows)
+{
+    /* Ingress Pre-Hairpin/Nat-Hairpin/Hairpin tabled (Priority 0).
+     * Packets that don't need hairpinning should continue processing.
      */
     ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 0, "1", "next;");
-
-    /* Ingress Hairpin table.
-     * - Priority 0: Packets that don't need hairpinning should continue
-     *   processing.
-     * - Priority 1: Packets that were SNAT-ed for hairpinning should be
-     *   looped back (i.e., swap ETH addresses and send back on inport).
-     */
-    ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 1, REGBIT_HAIRPIN " == 1",
-                  "eth.dst <-> eth.src;"
-                  "outport = inport;"
-                  "flags.loopback = 1;"
-                  "output;");
+    ovn_lflow_add(lflows, od, S_SWITCH_IN_NAT_HAIRPIN, 0, "1", "next;");
     ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 0, "1", "next;");
+
+    if (has_lb_vip(od)) {
+        /* Check if the packet needs to be hairpinned. */
+        ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 100,
+                                "ip && ct.trk && ct.dnat",
+                                REGBIT_HAIRPIN " = chk_lb_hairpin(); next;",
+                                &od->nbs->header_);
+
+        /* Check if the packet is a reply of hairpinned traffic. */
+        ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 90, "ip",
+                                REGBIT_HAIRPIN " = chk_lb_hairpin_reply(); "
+                                "next;", &od->nbs->header_);
+
+        /* If packet needs to be hairpinned, snat the src ip with the VIP. */
+        ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_NAT_HAIRPIN, 100,
+                                "ip && (ct.new || ct.est) && ct.trk && ct.dnat"
+                                " && "REGBIT_HAIRPIN " == 1",
+                                "ct_snat_to_vip; next;",
+                                &od->nbs->header_);
+
+        /* For the reply of hairpinned traffic, snat the src ip to the VIP. */
+        ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_NAT_HAIRPIN, 90,
+                                "ip && "REGBIT_HAIRPIN " == 1", "ct_snat;",
+                                &od->nbs->header_);
+
+        /* Ingress Hairpin table.
+        * - Priority 1: Packets that were SNAT-ed for hairpinning should be
+        *   looped back (i.e., swap ETH addresses and send back on inport).
+        */
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 1,
+                      REGBIT_HAIRPIN " == 1",
+                      "eth.dst <-> eth.src;"
+                      "outport = inport;"
+                      "flags.loopback = 1;"
+                      "output;");
+    }
 }
 
 /* Build logical flows for the forwarding groups */
@@ -7360,6 +7305,7 @@ build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od,
         build_qos(od, lflows);
         build_lb(od, lflows);
         build_stateful(od, lflows, lbs);
+        build_lb_hairpin(od, lflows);
     }
 }
 
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 7805763445..85f61f3577 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -1728,13 +1728,13 @@ action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implici
 AT_CHECK([grep "ls_out_acl" sw0flows | grep pg0 | sort], [0], [dnl
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=(outport == @pg0 && ip6 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
 ])
 
 AT_CHECK([grep "ls_out_acl" sw1flows | grep pg0 | sort], [0], [dnl
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=(outport == @pg0 && ip6 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
 ])
 
 AS_BOX([2])
@@ -1749,19 +1749,19 @@ AT_CAPTURE_FILE([sw1flows2])
 AT_CHECK([grep "ls_out_acl" sw0flows2 | grep pg0 | sort], [0], [dnl
   table=5 (ls_out_acl         ), priority=2002 , dnl
 match=(outport == @pg0 && ip4 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=(outport == @pg0 && ip6 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
 ])
 
 AT_CHECK([grep "ls_out_acl" sw1flows2 | grep pg0 | sort], [0], [dnl
   table=5 (ls_out_acl         ), priority=2002 , dnl
 match=(outport == @pg0 && ip4 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=(outport == @pg0 && ip6 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
 ])
 
 AS_BOX([3])
@@ -1780,16 +1780,16 @@ match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
 match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
   table=5 (ls_out_acl         ), priority=2002 , dnl
 match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), dnl
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2002 , dnl
 match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), dnl
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
 ])
 
 AT_CHECK([grep "ls_out_acl" sw1flows3 | grep pg0 | sort], [0], [dnl
@@ -1799,16 +1799,16 @@ match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
 match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
   table=5 (ls_out_acl         ), priority=2002 , dnl
 match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), dnl
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2002 , dnl
 match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), dnl
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
   table=5 (ls_out_acl         ), priority=2003 , dnl
 match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), dnl
-action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=21); };)
 ])
 
 AT_CLEANUP
diff --git a/tests/ovn.at b/tests/ovn.at
index 4883ddb8fc..2253d0bde1 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -15093,7 +15093,7 @@ logical_port=ls1-lp_ext1`
 # There should be a flow in hv2 to drop traffic from ls1-lp_ext1 destined
 # to router mac.
 AT_CHECK([as hv2 ovs-ofctl dump-flows br-int \
-table=27,dl_src=f0:00:00:00:00:03,dl_dst=a0:10:00:00:00:01 | \
+table=28,dl_src=f0:00:00:00:00:03,dl_dst=a0:10:00:00:00:01 | \
 grep -c "actions=drop"], [0], [1
 ])
 
-- 
2.28.0



More information about the dev mailing list