[ovs-dev] [PATCH ovn v2 1/2] northd: Optimize ct nat for load balancer traffic.

Numan Siddique numans at ovn.org
Mon Apr 19 20:51:37 UTC 2021


On Fri, Apr 16, 2021 at 4:52 AM Mark Gray <mark.d.gray at redhat.com> wrote:
>
> I noticed some tests failing but I think the ddlog tests look flakey as
> I saw other failures without these patches.
>
> I did my best to review the ddlog part but I am not familiar with ddlog

Thanks for the reviews.  Please see below for few comments.


>
> On 12/04/2021 15:41, numans at ovn.org wrote:
> > From: Numan Siddique <numans at ovn.org>
> >
> > For a load balancer traffic destined to VIP, we do the below actions
> > related to conntrack in the ingress logical switch pipeline.
> >   1.  Send the packet to conntrack - ct()
> >   2a. if ct.new then ct_lb(backends)
> >   2b. if ct.est then ct(nat)
> >
> > The step 2b is unnecessary and can be removed to avoid another
> > recirculation.
> >
> > This patch improves this by doing the below.
> >
> > For a load balancer traffic destined to VIP, we will now do
> >   1.   ct(nat)
> >   2a.  if ct.new - ct_lb(backends)
> >   2b.  if ct.est, no further action related to conntrack.
> >
> > For non load balancer connection traffic, we will now do
> >   1.  ct(nat)
> >   2a. if ct.new then ct(commit)
> >   2b  if ct.est, no further action related to conntrack.
> >
> > The same improvement is done for the egress logical switch
> > pipeline.  The stages - ls_in_lb and ls_out_lb are removed
> > since these stages are no longer needed.
> >
> > Signed-off-by: Numan Siddique <numans at ovn.org>
> > ---
> >  northd/ovn-northd.8.xml | 150 ++++++++++++-----------
> >  northd/ovn-northd.c     | 154 +++++++++--------------
> >  northd/ovn_northd.dl    | 184 ++++++++++------------------
> >  tests/ovn-northd.at     | 265 ++++++++++++++++++++++++++++++----------
> >  tests/ovn.at            | 177 ++++++++++++++-------------
> >  5 files changed, 495 insertions(+), 435 deletions(-)
> >
> > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> > index a62f5c057a..6b295c8e63 100644
> > --- a/northd/ovn-northd.8.xml
> > +++ b/northd/ovn-northd.8.xml
> > @@ -443,10 +443,11 @@
> >        addresses (and ports) are configured in <code>OVN_Northbound</code>
> >        database for alogical switch datapath, a priority-100 flow is added
>
> You did not introduce it^ but perhaps you could fix.
>
> s/alogical/a logical

Ack

>
> >        with the match <code>ip</code> to match on IP packets and sets the action
> > -      <code>reg0[0] = 1; next;</code> to act as a hint for table
> > +      <code>reg0[2] = 1; next;</code> to act as a hint for table
> >        <code>Pre-stateful</code> to send IP packets to the connection tracker
> > -      for packet de-fragmentation before eventually advancing to ingress
> > -      table <code>LB</code>.
> > +      for packet de-fragmentation (and to possibly do dnat for already
>
> Maybe capitalize to "DNAT" to keep consistent with the rest of the man page
Ack

> > +      established load balanced traffic) before eventually advancing to ingress
> > +      table <code>Stateful</code>.
> >        If controller_event has been enabled and load balancing rules with
> >        empty backends have been added in <code>OVN_Northbound</code>, a 130 flow
> >        is added to trigger ovn-controller events whenever the chassis receives a
> > @@ -504,11 +505,38 @@
> >      <p>
> >        This table prepares flows for all possible stateful processing
> >        in next tables.  It contains a priority-0 flow that simply moves
> > -      traffic to the next table.  A priority-100 flow sends the packets to
> > -      connection tracker based on a hint provided by the previous tables
> > -      (with a match for <code>reg0[0] == 1</code>) by using the
> > -      <code>ct_next;</code> action.
> > +      traffic to the next table.
> >      </p>
> > +    <ul>
> > +      <li>
> > +        Priority-120 flows that send the packets to connection tracker using
> > +        <code>ct_lb;</code> as the action so that the already established
> > +        traffic destined to the load balancer VIP gets dnatted based on a hint
>
> DNATted

Ack.

> > +        provided by the previous tables (with a match
> > +        for <code>reg0[2] == 1</code> and on supported load balancer protocols
> > +        and address families).  For IPv4 traffic the flows also load the
> > +        original destination IP and transport port in registers
> > +        <code>reg1</code> and <code>reg2</code>.  For IPv6 traffic the flows
> > +        also load the original destination IP and transport port in
> > +        registers <code>xxreg1</code> and <code>reg2</code>.
> > +      </li>
> > +
> > +      <li>
> > +         A priority-110 flow sends the packets to connection tracker based
> > +         on a hint provided by the previous tables
> > +         (with a match for <code>reg0[2] == 1</code>) by using the
> > +         <code>ct_lb;</code> action.  This flow is added to handle
> > +         the traffic for load balancer VIPs whose protocol is not defined
> > +         (mainly for ICMP traffic).
> > +      </li>
> > +
> > +      <li>
> > +         A priority-100 flow sends the packets to connection tracker based
> > +         on a hint provided by the previous tables
> > +         (with a match for <code>reg0[0] == 1</code>) by using the
> > +         <code>ct_next;</code> action.
> > +      </li>
> > +    </ul>
> >
> >      <h3>Ingress Table 8: <code>from-lport</code> ACL hints</h3>
> >
> > @@ -743,33 +771,7 @@
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 12: LB</h3>
> > -
> > -    <p>
> > -      It contains a priority-0 flow that simply moves traffic to the next
> > -      table.
> > -    </p>
> > -
> > -    <p>
> > -      A priority-65535 flow with the match
> > -      <code>inport == <var>I</var></code> for all logical switch
> > -      datapaths to move traffic to the next table. Where <var>I</var>
> > -      is the peer of a logical router port. This flow is added to
> > -      skip the connection tracking of packets which enter from
> > -      logical router datapath to logical switch datapath.
> > -    </p>
> > -
> > -    <p>
> > -      For established connections a priority 65534 flow matches on
> > -      <code>ct.est && !ct.rel && !ct.new &&
> > -      !ct.inv</code> and sets an action <code>reg0[2] = 1; next;</code> to act
> > -      as a hint for table <code>Stateful</code> to send packets through
> > -      connection tracker to NAT the packets.  (The packet will automatically
> > -      get DNATed to the same IP address as the first packet in that
> > -      connection.)
> > -    </p>
> > -
> > -    <h3>Ingress Table 13: Stateful</h3>
> > +    <h3>Ingress Table 12: Stateful</h3>
> >
> >      <ul>
> >        <li>
> > @@ -826,23 +828,12 @@
> >          <code>ct_commit; next;</code> action based on a hint provided by
> >          the previous tables (with a match for <code>reg0[1] == 1</code>).
> >        </li>
> > -      <li>
> > -        Priority-100 flows that send the packets to connection tracker using
> > -        <code>ct_lb;</code> as the action based on a hint provided by the
> > -        previous tables (with a match for <code>reg0[2] == 1</code> and
> > -        on supported load balancer protocols and address families).
> > -        For IPv4 traffic the flows also load the original destination
> > -        IP and transport port in registers <code>reg1</code> and
> > -        <code>reg2</code>.  For IPv6 traffic the flows also load the original
> > -        destination IP and transport port in registers <code>xxreg1</code> and
> > -        <code>reg2</code>.
> > -      </li>
> >        <li>
> >          A priority-0 flow that simply moves traffic to the next table.
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 14: Pre-Hairpin</h3>
> > +    <h3>Ingress Table 13: Pre-Hairpin</h3>
> >      <ul>
> >        <li>
> >          If the logical switch has load balancer(s) configured, then a
> > @@ -860,7 +851,7 @@
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 15: Nat-Hairpin</h3>
> > +    <h3>Ingress Table 14: Nat-Hairpin</h3>
> >      <ul>
> >        <li>
> >           If the logical switch has load balancer(s) configured, then a
> > @@ -895,7 +886,7 @@
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 16: Hairpin</h3>
> > +    <h3>Ingress Table 15: Hairpin</h3>
> >      <ul>
> >        <li>
> >          A priority-1 flow that hairpins traffic matched by non-default
> > @@ -908,7 +899,7 @@
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 17: ARP/ND responder</h3>
> > +    <h3>Ingress Table 16: ARP/ND responder</h3>
> >
> >      <p>
> >        This table implements ARP/ND responder in a logical switch for known
> > @@ -1198,7 +1189,7 @@ output;
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 18: DHCP option processing</h3>
> > +    <h3>Ingress Table 17: DHCP option processing</h3>
> >
> >      <p>
> >        This table adds the DHCPv4 options to a DHCPv4 packet from the
> > @@ -1259,7 +1250,7 @@ next;
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 19: DHCP responses</h3>
> > +    <h3>Ingress Table 18: DHCP responses</h3>
> >
> >      <p>
> >        This table implements DHCP responder for the DHCP replies generated by
> > @@ -1340,7 +1331,7 @@ output;
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 20 DNS Lookup</h3>
> > +    <h3>Ingress Table 19 DNS Lookup</h3>
> >
> >      <p>
> >        This table looks up and resolves the DNS names to the corresponding
> > @@ -1369,7 +1360,7 @@ reg0[4] = dns_lookup(); next;
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 21 DNS Responses</h3>
> > +    <h3>Ingress Table 20 DNS Responses</h3>
> >
> >      <p>
> >        This table implements DNS responder for the DNS replies generated by
> > @@ -1404,7 +1395,7 @@ output;
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress table 22 External ports</h3>
> > +    <h3>Ingress table 21 External ports</h3>
> >
> >      <p>
> >        Traffic from the <code>external</code> logical ports enter the ingress
> > @@ -1447,7 +1438,7 @@ output;
> >        </li>
> >      </ul>
> >
> > -    <h3>Ingress Table 23 Destination Lookup</h3>
> > +    <h3>Ingress Table 22 Destination Lookup</h3>
> >
> >      <p>
> >        This table implements switching behavior.  It contains these logical
> > @@ -1673,9 +1664,11 @@ output;
> >        Moreover it contains a priority-110 flow to move IPv6 Neighbor Discovery
> >        traffic to the next table. If any load balancing rules exist for the
> >        datapath, a priority-100 flow is added with a match of <code>ip</code>
> > -      and action of <code>reg0[0] = 1; next;</code> to act as a hint for
> > +      and action of <code>reg0[2] = 1; next;</code> to act as a hint for
> >        table <code>Pre-stateful</code> to send IP packets to the connection
> > -      tracker for packet de-fragmentation.
> > +      tracker for packet de-fragmentation and possibly dnat the destination
>
> Maybe DNAT

Ack

> > +      VIP to one of the selected backend for already commited load balanced
> > +      traffic.
> >      </p>
> >
> >      <p>
> > @@ -1717,20 +1710,39 @@ output;
> >      <h3>Egress Table 2: Pre-stateful</h3>
> >
> >      <p>
> > -      This is similar to ingress table <code>Pre-stateful</code>.
> > +      This is similar to ingress table <code>Pre-stateful</code>.  This table
> > +      adds the below 3 logical flows.
> >      </p>
> >
> > -    <h3>Egress Table 3: LB</h3>
> > -    <p>
> > -      This is similar to ingress table <code>LB</code>.
> > -    </p>
> > +    <ul>
> > +      <li>
> > +        A Priority-120 flow that send the packets to connection tracker using
> > +        <code>ct_lb;</code> as the action so that the already established
> > +        traffic gets undnatted from the backend IP to the load balancer VIP
>
> I see "unDNATted" as the spelling elsewhere. Maybe you could change to
> keep consistent.

Ack

>
> > +        based on a hint provided by the previous tables with a match
> > +        for <code>reg0[2] == 1</code>.  If the packet was not dnatted earlier,
>
> Maybe DNATted

Ack

> > +        then <code>ct_lb</code> functions like <code>ct_next</code>.
> > +      </li>
> > +
> > +      <li>
> > +        A priority-100 flow sends the packets to connection tracker based
> > +        on a hint provided by the previous tables
> > +        (with a match for <code>reg0[0] == 1</code>) by using the
> > +        <code>ct_next;</code> action.
> > +      </li>
> > +
> > +      <li>
> > +        A priority-0 flow that matches all packets to advance to the next
> > +        table.
> > +      </li>
> > +    </ul>
> >
> > -    <h3>Egress Table 4: <code>from-lport</code> ACL hints</h3>
> > +    <h3>Egress Table 3: <code>from-lport</code> ACL hints</h3>
> >      <p>
> >        This is similar to ingress table <code>ACL hints</code>.
> >      </p>
> >
> > -    <h3>Egress Table 5: <code>to-lport</code> ACLs</h3>
> > +    <h3>Egress Table 4: <code>to-lport</code> ACLs</h3>
> >
> >      <p>
> >        This is similar to ingress table <code>ACLs</code> except for
> > @@ -1767,28 +1779,28 @@ output;
> >        </li>
> >      </ul>
> >
> > -    <h3>Egress Table 6: <code>to-lport</code> QoS Marking</h3>
> > +    <h3>Egress Table 5: <code>to-lport</code> QoS Marking</h3>
> >
> >      <p>
> >        This is similar to ingress table <code>QoS marking</code> except
> >        they apply to <code>to-lport</code> QoS rules.
> >      </p>
> >
> > -    <h3>Egress Table 7: <code>to-lport</code> QoS Meter</h3>
> > +    <h3>Egress Table 6: <code>to-lport</code> QoS Meter</h3>
> >
> >      <p>
> >        This is similar to ingress table <code>QoS meter</code> except
> >        they apply to <code>to-lport</code> QoS rules.
> >      </p>
> >
> > -    <h3>Egress Table 8: Stateful</h3>
> > +    <h3>Egress Table 7: Stateful</h3>
> >
> >      <p>
> >        This is similar to ingress table <code>Stateful</code> except that
> >        there are no rules added for load balancing new connections.
> >      </p>
> >
> > -    <h3>Egress Table 9: Egress Port Security - IP</h3>
> > +    <h3>Egress Table 8: Egress Port Security - IP</h3>
> >
> >      <p>
> >        This is similar to the port security logic in table
> > @@ -1798,7 +1810,7 @@ output;
> >        <code>ip4.src</code> and <code>ip6.src</code>
> >      </p>
> >
> > -    <h3>Egress Table 10: Egress Port Security - L2</h3>
> > +    <h3>Egress Table 9: Egress Port Security - L2</h3>
> >
> >      <p>
> >        This is similar to the ingress port security logic in ingress table
> > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> > index 9839b8c4f5..637d3a10a9 100644
> > --- a/northd/ovn-northd.c
> > +++ b/northd/ovn-northd.c
> > @@ -147,32 +147,30 @@ enum ovn_stage {
> >      PIPELINE_STAGE(SWITCH, IN,  ACL,            9, "ls_in_acl")           \
> >      PIPELINE_STAGE(SWITCH, IN,  QOS_MARK,      10, "ls_in_qos_mark")      \
> >      PIPELINE_STAGE(SWITCH, IN,  QOS_METER,     11, "ls_in_qos_meter")     \
> > -    PIPELINE_STAGE(SWITCH, IN,  LB,            12, "ls_in_lb")            \
> > -    PIPELINE_STAGE(SWITCH, IN,  STATEFUL,      13, "ls_in_stateful")      \
> > -    PIPELINE_STAGE(SWITCH, IN,  PRE_HAIRPIN,   14, "ls_in_pre_hairpin")   \
> > -    PIPELINE_STAGE(SWITCH, IN,  NAT_HAIRPIN,   15, "ls_in_nat_hairpin")   \
> > -    PIPELINE_STAGE(SWITCH, IN,  HAIRPIN,       16, "ls_in_hairpin")       \
> > -    PIPELINE_STAGE(SWITCH, IN,  ARP_ND_RSP,    17, "ls_in_arp_rsp")       \
> > -    PIPELINE_STAGE(SWITCH, IN,  DHCP_OPTIONS,  18, "ls_in_dhcp_options")  \
> > -    PIPELINE_STAGE(SWITCH, IN,  DHCP_RESPONSE, 19, "ls_in_dhcp_response") \
> > -    PIPELINE_STAGE(SWITCH, IN,  DNS_LOOKUP,    20, "ls_in_dns_lookup")    \
> > -    PIPELINE_STAGE(SWITCH, IN,  DNS_RESPONSE,  21, "ls_in_dns_response")  \
> > -    PIPELINE_STAGE(SWITCH, IN,  EXTERNAL_PORT, 22, "ls_in_external_port") \
> > -    PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,       23, "ls_in_l2_lkup")       \
> > -    PIPELINE_STAGE(SWITCH, IN,  L2_UNKNOWN,    24, "ls_in_l2_unknown")    \
> > +    PIPELINE_STAGE(SWITCH, IN,  STATEFUL,      12, "ls_in_stateful")      \
> > +    PIPELINE_STAGE(SWITCH, IN,  PRE_HAIRPIN,   13, "ls_in_pre_hairpin")   \
> > +    PIPELINE_STAGE(SWITCH, IN,  NAT_HAIRPIN,   14, "ls_in_nat_hairpin")   \
> > +    PIPELINE_STAGE(SWITCH, IN,  HAIRPIN,       15, "ls_in_hairpin")       \
> > +    PIPELINE_STAGE(SWITCH, IN,  ARP_ND_RSP,    16, "ls_in_arp_rsp")       \
> > +    PIPELINE_STAGE(SWITCH, IN,  DHCP_OPTIONS,  17, "ls_in_dhcp_options")  \
> > +    PIPELINE_STAGE(SWITCH, IN,  DHCP_RESPONSE, 18, "ls_in_dhcp_response") \
> > +    PIPELINE_STAGE(SWITCH, IN,  DNS_LOOKUP,    19, "ls_in_dns_lookup")    \
> > +    PIPELINE_STAGE(SWITCH, IN,  DNS_RESPONSE,  20, "ls_in_dns_response")  \
> > +    PIPELINE_STAGE(SWITCH, IN,  EXTERNAL_PORT, 21, "ls_in_external_port") \
> > +    PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,       22, "ls_in_l2_lkup")       \
> > +    PIPELINE_STAGE(SWITCH, IN,  L2_UNKNOWN,    23, "ls_in_l2_unknown")    \
> >                                                                            \
> >      /* Logical switch egress stages. */                                   \
> >      PIPELINE_STAGE(SWITCH, OUT, PRE_LB,       0, "ls_out_pre_lb")         \
> >      PIPELINE_STAGE(SWITCH, OUT, PRE_ACL,      1, "ls_out_pre_acl")        \
> >      PIPELINE_STAGE(SWITCH, OUT, PRE_STATEFUL, 2, "ls_out_pre_stateful")   \
> > -    PIPELINE_STAGE(SWITCH, OUT, LB,           3, "ls_out_lb")             \
> > -    PIPELINE_STAGE(SWITCH, OUT, ACL_HINT,     4, "ls_out_acl_hint")       \
> > -    PIPELINE_STAGE(SWITCH, OUT, ACL,          5, "ls_out_acl")            \
> > -    PIPELINE_STAGE(SWITCH, OUT, QOS_MARK,     6, "ls_out_qos_mark")       \
> > -    PIPELINE_STAGE(SWITCH, OUT, QOS_METER,    7, "ls_out_qos_meter")      \
> > -    PIPELINE_STAGE(SWITCH, OUT, STATEFUL,     8, "ls_out_stateful")       \
> > -    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_IP,  9, "ls_out_port_sec_ip")    \
> > -    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2, 10, "ls_out_port_sec_l2")    \
> > +    PIPELINE_STAGE(SWITCH, OUT, ACL_HINT,     3, "ls_out_acl_hint")       \
> > +    PIPELINE_STAGE(SWITCH, OUT, ACL,          4, "ls_out_acl")            \
> > +    PIPELINE_STAGE(SWITCH, OUT, QOS_MARK,     5, "ls_out_qos_mark")       \
> > +    PIPELINE_STAGE(SWITCH, OUT, QOS_METER,    6, "ls_out_qos_meter")      \
> > +    PIPELINE_STAGE(SWITCH, OUT, STATEFUL,     7, "ls_out_stateful")       \
> > +    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_IP,  8, "ls_out_port_sec_ip")    \
> > +    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2,  9, "ls_out_port_sec_l2")    \
> >                                                                        \
> >      /* Logical router ingress stages. */                              \
> >      PIPELINE_STAGE(ROUTER, IN,  ADMISSION,       0, "lr_in_admission")    \
> > @@ -5159,9 +5157,9 @@ build_pre_lb(struct ovn_datapath *od, struct hmap *lflows,
> >       */>      if (vip_configured) {
> >          ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_LB,
> > -                      100, "ip", REGBIT_CONNTRACK_DEFRAG" = 1; next;");
> > +                      100, "ip", REGBIT_CONNTRACK_NAT" = 1; next;");
> >          ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_LB,
> > -                      100, "ip", REGBIT_CONNTRACK_DEFRAG" = 1; next;");
> > +                      100, "ip", REGBIT_CONNTRACK_NAT" = 1; next;");
> >      }
>
> The comment above this that describes this code^ needs to be changed.

Ack.

> >  }
> >
> > @@ -5173,10 +5171,46 @@ build_pre_stateful(struct ovn_datapath *od, struct hmap *lflows)
> >      ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 0, "1", "next;");
> >      ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_STATEFUL, 0, "1", "next;");
> >
> > +    const char *lb_protocols[] = {"tcp", "udp", "sctp"};
> > +    struct ds actions = DS_EMPTY_INITIALIZER;
> > +    struct ds match = DS_EMPTY_INITIALIZER;
> > +
> > +    for (size_t i = 0; i < ARRAY_SIZE(lb_protocols); i++) {
> > +        ds_clear(&match);
> > +        ds_clear(&actions);
> > +        ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip4 && %s",
> > +                      lb_protocols[i]);
> > +        ds_put_format(&actions, REG_ORIG_DIP_IPV4 " = ip4.dst; "
> > +                                REG_ORIG_TP_DPORT " = %s.dst; ct_lb;",
> > +                      lb_protocols[i]);
> > +        ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 120,
> > +                      ds_cstr(&match), ds_cstr(&actions));
> > +
> > +        ds_clear(&match);
> > +        ds_clear(&actions);
> > +        ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip6 && %s",
> > +                      lb_protocols[i]);
> > +        ds_put_format(&actions, REG_ORIG_DIP_IPV6 " = ip6.dst; "
> > +                                REG_ORIG_TP_DPORT " = %s.dst; ct_lb;",
> > +                      lb_protocols[i]);
> > +        ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 120,
> > +                      ds_cstr(&match), ds_cstr(&actions));
> > +    }
> > +
> > +    ds_destroy(&actions);
> > +    ds_destroy(&match);
> > +
> > +    ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 110,
> > +                  REGBIT_CONNTRACK_NAT" == 1", "ct_lb;");
> > +
> > +    ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_STATEFUL, 110,
> > +                  REGBIT_CONNTRACK_NAT" == 1", "ct_lb;");
> > +
> >      /* If REGBIT_CONNTRACK_DEFRAG is set as 1, then the packets should be
> >       * sent to conntrack for tracking and defragmentation. */
> >      ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 100,
> >                    REGBIT_CONNTRACK_DEFRAG" == 1", "ct_next;");
> > +>      ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_STATEFUL, 100,
> >                    REGBIT_CONNTRACK_DEFRAG" == 1", "ct_next;");
> >  }
> > @@ -5856,37 +5890,6 @@ build_qos(struct ovn_datapath *od, struct hmap *lflows) {
> >      }
> >  }
> >
> > -static void
> > -build_lb(struct ovn_datapath *od, struct hmap *lflows)
> > -{
> > -    /* Ingress and Egress LB Table (Priority 0): Packets are allowed by
> > -     * default.  */
> > -    ovn_lflow_add(lflows, od, S_SWITCH_IN_LB, 0, "1", "next;");
> > -    ovn_lflow_add(lflows, od, S_SWITCH_OUT_LB, 0, "1", "next;");
> > -
> > -    if (od->nbs->n_load_balancer) {
> > -        for (size_t i = 0; i < od->n_router_ports; i++) {
> > -            skip_port_from_conntrack(od, od->router_ports[i],
> > -                                     S_SWITCH_IN_LB, S_SWITCH_OUT_LB,
> > -                                     UINT16_MAX, lflows);
> > -        }
> > -    }
> > -
> > -    if (od->has_lb_vip) {
> > -        /* Ingress and Egress LB Table (Priority 65534).
> > -         *
> > -         * Send established traffic through conntrack for just NAT. */
> > -        ovn_lflow_add(lflows, od, S_SWITCH_IN_LB, UINT16_MAX - 1,
> > -                      "ct.est && !ct.rel && !ct.new && !ct.inv && "
> > -                      "ct_label.natted == 1",
> > -                      REGBIT_CONNTRACK_NAT" = 1; next;");
> > -        ovn_lflow_add(lflows, od, S_SWITCH_OUT_LB, UINT16_MAX - 1,
> > -                      "ct.est && !ct.rel && !ct.new && !ct.inv && "
> > -                      "ct_label.natted == 1",
> > -                      REGBIT_CONNTRACK_NAT" = 1; next;");
> > -    }
> > -}
> > -
> >  static void
> >  build_lb_rules(struct ovn_datapath *od, struct hmap *lflows,
> >                 struct ovn_northd_lb *lb)
> > @@ -5971,48 +5974,6 @@ build_stateful(struct ovn_datapath *od, struct hmap *lflows, struct hmap *lbs)
> >                    REGBIT_CONNTRACK_COMMIT" == 1",
> >                    "ct_commit { ct_label.blocked = 0; }; next;");
> >
> > -    /* If REGBIT_CONNTRACK_NAT is set as 1, then packets should just be sent
> > -     * through nat (without committing).
> > -     *
> > -     * REGBIT_CONNTRACK_COMMIT is set for new connections and
> > -     * REGBIT_CONNTRACK_NAT is set for established connections. So they
> > -     * don't overlap.
> > -     *
> > -     * In the ingress pipeline, also store the original destination IP and
> > -     * transport port to be used when detecting hairpin packets.
> > -     */
> > -    const char *lb_protocols[] = {"tcp", "udp", "sctp"};
> > -    struct ds actions = DS_EMPTY_INITIALIZER;
> > -    struct ds match = DS_EMPTY_INITIALIZER;
> > -
> > -    for (size_t i = 0; i < ARRAY_SIZE(lb_protocols); i++) {
> > -        ds_clear(&match);
> > -        ds_clear(&actions);
> > -        ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip4 && %s",
> > -                      lb_protocols[i]);
> > -        ds_put_format(&actions, REG_ORIG_DIP_IPV4 " = ip4.dst; "
> > -                                REG_ORIG_TP_DPORT " = %s.dst; ct_lb;",
> > -                      lb_protocols[i]);
> > -        ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100,
> > -                      ds_cstr(&match), ds_cstr(&actions));
> > -
> > -        ds_clear(&match);
> > -        ds_clear(&actions);
> > -        ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip6 && %s",
> > -                      lb_protocols[i]);
> > -        ds_put_format(&actions, REG_ORIG_DIP_IPV6 " = ip6.dst; "
> > -                                REG_ORIG_TP_DPORT " = %s.dst; ct_lb;",
> > -                      lb_protocols[i]);
> > -        ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100,
> > -                      ds_cstr(&match), ds_cstr(&actions));
> > -    }
> > -
> > -    ds_destroy(&actions);
> > -    ds_destroy(&match);
> > -
> > -    ovn_lflow_add(lflows, od, S_SWITCH_OUT_STATEFUL, 100,
> > -                  REGBIT_CONNTRACK_NAT" == 1", "ct_lb;");
> > -
> >      /* Load balancing rules for new connections get committed to conntrack
> >       * table.  So even if REGBIT_CONNTRACK_COMMIT is set in a previous table
> >       * a higher priority rule for load balancing below also commits the
> > @@ -6803,7 +6764,6 @@ build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od,
>
> I think the comment above this function is wrong now as it references
> table numbers.

Ack.

>
> >          build_acl_hints(od, lflows);
> >          build_acls(od, lflows, port_groups, meter_groups);
> >          build_qos(od, lflows);
> > -        build_lb(od, lflows);
> >          build_stateful(od, lflows, lbs);
> >          build_lb_hairpin(od, lflows);
> >      }
> > diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
> > index 0063021e13..2c0796938c 100644
> > --- a/northd/ovn_northd.dl
> > +++ b/northd/ovn_northd.dl
> > @@ -1398,32 +1398,30 @@ function s_SWITCH_IN_ACL_HINT():        Stage { Stage{Ingress,  8, "ls_in_acl_hi
> >  function s_SWITCH_IN_ACL():             Stage { Stage{Ingress,  9, "ls_in_acl"} }
> >  function s_SWITCH_IN_QOS_MARK():        Stage { Stage{Ingress, 10, "ls_in_qos_mark"} }
> >  function s_SWITCH_IN_QOS_METER():       Stage { Stage{Ingress, 11, "ls_in_qos_meter"} }
> > -function s_SWITCH_IN_LB():              Stage { Stage{Ingress, 12, "ls_in_lb"} }
> > -function s_SWITCH_IN_STATEFUL():        Stage { Stage{Ingress, 13, "ls_in_stateful"} }
> > -function s_SWITCH_IN_PRE_HAIRPIN():     Stage { Stage{Ingress, 14, "ls_in_pre_hairpin"} }
> > -function s_SWITCH_IN_NAT_HAIRPIN():     Stage { Stage{Ingress, 15, "ls_in_nat_hairpin"} }
> > -function s_SWITCH_IN_HAIRPIN():         Stage { Stage{Ingress, 16, "ls_in_hairpin"} }
> > -function s_SWITCH_IN_ARP_ND_RSP():      Stage { Stage{Ingress, 17, "ls_in_arp_rsp"} }
> > -function s_SWITCH_IN_DHCP_OPTIONS():    Stage { Stage{Ingress, 18, "ls_in_dhcp_options"} }
> > -function s_SWITCH_IN_DHCP_RESPONSE():   Stage { Stage{Ingress, 19, "ls_in_dhcp_response"} }
> > -function s_SWITCH_IN_DNS_LOOKUP():      Stage { Stage{Ingress, 20, "ls_in_dns_lookup"} }
> > -function s_SWITCH_IN_DNS_RESPONSE():    Stage { Stage{Ingress, 21, "ls_in_dns_response"} }
> > -function s_SWITCH_IN_EXTERNAL_PORT():   Stage { Stage{Ingress, 22, "ls_in_external_port"} }
> > -function s_SWITCH_IN_L2_LKUP():         Stage { Stage{Ingress, 23, "ls_in_l2_lkup"} }
> > -function s_SWITCH_IN_L2_UNKNOWN():      Stage { Stage{Ingress, 24, "ls_in_l2_unknown"} }
> > +function s_SWITCH_IN_STATEFUL():        Stage { Stage{Ingress, 12, "ls_in_stateful"} }
> > +function s_SWITCH_IN_PRE_HAIRPIN():     Stage { Stage{Ingress, 13, "ls_in_pre_hairpin"} }
> > +function s_SWITCH_IN_NAT_HAIRPIN():     Stage { Stage{Ingress, 14, "ls_in_nat_hairpin"} }
> > +function s_SWITCH_IN_HAIRPIN():         Stage { Stage{Ingress, 15, "ls_in_hairpin"} }
> > +function s_SWITCH_IN_ARP_ND_RSP():      Stage { Stage{Ingress, 16, "ls_in_arp_rsp"} }
> > +function s_SWITCH_IN_DHCP_OPTIONS():    Stage { Stage{Ingress, 17, "ls_in_dhcp_options"} }
> > +function s_SWITCH_IN_DHCP_RESPONSE():   Stage { Stage{Ingress, 18, "ls_in_dhcp_response"} }
> > +function s_SWITCH_IN_DNS_LOOKUP():      Stage { Stage{Ingress, 19, "ls_in_dns_lookup"} }
> > +function s_SWITCH_IN_DNS_RESPONSE():    Stage { Stage{Ingress, 20, "ls_in_dns_response"} }
> > +function s_SWITCH_IN_EXTERNAL_PORT():   Stage { Stage{Ingress, 21, "ls_in_external_port"} }
> > +function s_SWITCH_IN_L2_LKUP():         Stage { Stage{Ingress, 22, "ls_in_l2_lkup"} }
> > +function s_SWITCH_IN_L2_UNKNOWN():      Stage { Stage{Ingress, 23, "ls_in_l2_unknown"} }
> >
> >  /* Logical switch egress stages. */
> >  function s_SWITCH_OUT_PRE_LB():         Stage { Stage{ Egress,  0, "ls_out_pre_lb"} }
> >  function s_SWITCH_OUT_PRE_ACL():        Stage { Stage{ Egress,  1, "ls_out_pre_acl"} }
> >  function s_SWITCH_OUT_PRE_STATEFUL():   Stage { Stage{ Egress,  2, "ls_out_pre_stateful"} }
> > -function s_SWITCH_OUT_LB():             Stage { Stage{ Egress,  3, "ls_out_lb"} }
> > -function s_SWITCH_OUT_ACL_HINT():       Stage { Stage{ Egress,  4, "ls_out_acl_hint"} }
> > -function s_SWITCH_OUT_ACL():            Stage { Stage{ Egress,  5, "ls_out_acl"} }
> > -function s_SWITCH_OUT_QOS_MARK():       Stage { Stage{ Egress,  6, "ls_out_qos_mark"} }
> > -function s_SWITCH_OUT_QOS_METER():      Stage { Stage{ Egress,  7, "ls_out_qos_meter"} }
> > -function s_SWITCH_OUT_STATEFUL():       Stage { Stage{ Egress,  8, "ls_out_stateful"} }
> > -function s_SWITCH_OUT_PORT_SEC_IP():    Stage { Stage{ Egress,  9, "ls_out_port_sec_ip"} }
> > -function s_SWITCH_OUT_PORT_SEC_L2():    Stage { Stage{ Egress, 10, "ls_out_port_sec_l2"} }
> > +function s_SWITCH_OUT_ACL_HINT():       Stage { Stage{ Egress,  3, "ls_out_acl_hint"} }
> > +function s_SWITCH_OUT_ACL():            Stage { Stage{ Egress,  4, "ls_out_acl"} }
> > +function s_SWITCH_OUT_QOS_MARK():       Stage { Stage{ Egress,  5, "ls_out_qos_mark"} }
> > +function s_SWITCH_OUT_QOS_METER():      Stage { Stage{ Egress,  6, "ls_out_qos_meter"} }
> > +function s_SWITCH_OUT_STATEFUL():       Stage { Stage{ Egress,  7, "ls_out_stateful"} }
> > +function s_SWITCH_OUT_PORT_SEC_IP():    Stage { Stage{ Egress,  8, "ls_out_port_sec_ip"} }
> > +function s_SWITCH_OUT_PORT_SEC_L2():    Stage { Stage{ Egress,  9, "ls_out_port_sec_l2"} }
> >
> >  /* Logical router ingress stages. */
> >  function s_ROUTER_IN_ADMISSION():       Stage { Stage{Ingress,  0, "lr_in_admission"} }
> > @@ -2049,7 +2047,7 @@ Flow(.logical_datapath = sw.ls._uuid,
> >      Some {(var __match, var __action)} = build_empty_lb_event_flow(
> >          vip, lb, has_elb_meter).
> >
> > -/* 'REGBIT_CONNTRACK_DEFRAG' is set to let the pre-stateful table send
> > +/* 'rEGBIT_CONNTRACK_NAT' is set to let the pre-stateful table send>   * packet to conntrack for defragmentation.
> >   *
> >   * Send all the packets to conntrack in the ingress pipeline if the
> > @@ -2083,17 +2081,21 @@ for (sw in &Switch(.has_lb_vip = true)) {
> >           .stage            = s_SWITCH_IN_PRE_LB(),
> >           .priority         = 100,
> >           .__match          = "ip",
> > -         .actions          = "${rEGBIT_CONNTRACK_DEFRAG()} = 1; next;",
> > +         .actions          = "${rEGBIT_CONNTRACK_NAT()} = 1; next;",
> >           .external_ids     = map_empty());
> >      Flow(.logical_datapath = sw.ls._uuid,
> >           .stage            = s_SWITCH_OUT_PRE_LB(),
> >           .priority         = 100,
> >           .__match          = "ip",
> > -         .actions          = "${rEGBIT_CONNTRACK_DEFRAG()} = 1; next;",
> > +         .actions          = "${rEGBIT_CONNTRACK_NAT()} = 1; next;",
> >           .external_ids     = map_empty())
> >  }
> >
> >  /* Pre-stateful */
> > +relation LbProtocol[string]
> > +LbProtocol["tcp"].
> > +LbProtocol["udp"].
> > +LbProtocol["sctp"].
> >  for (&Switch(.ls = ls)) {
> >      /* Ingress and Egress pre-stateful Table (Priority 0): Packets are
> >       * allowed by default. */
> > @@ -2110,6 +2112,47 @@ for (&Switch(.ls = ls)) {
> >           .actions          = "next;",
> >           .external_ids     = map_empty());
> >
> > +    /* If REGBIT_CONNTRACK_NAT is set as 1, then packets should just be sent
>
> should be rEGBIT? and below?
> > +     * through nat (without committing).
> > +     *
> > +     * REGBIT_CONNTRACK_COMMIT is set for new connections and
> > +     * REGBIT_CONNTRACK_NAT is set for established connections. So they
> > +     * don't overlap.
> > +     *
> > +     * In the ingress pipeline, also store the original destination IP and
> > +     * transport port to be used when detecting hairpin packets.
> > +     */
> > +    for (LbProtocol[protocol]) {
> > +        Flow(.logical_datapath = ls._uuid,
> > +             .stage            = s_SWITCH_IN_PRE_STATEFUL(),
> > +             .priority         = 120,
> > +             .__match          = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip4 && ${protocol}",
> > +             .actions          = "${rEG_ORIG_DIP_IPV4()} = ip4.dst; "
> > +                                 "${rEG_ORIG_TP_DPORT()} = ${protocol}.dst; ct_lb;",
> > +             .external_ids     = map_empty());
> > +        Flow(.logical_datapath = ls._uuid,
> > +             .stage            = s_SWITCH_IN_PRE_STATEFUL(),
> > +             .priority         = 120,
> > +             .__match          = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip6 && ${protocol}",
> > +             .actions          = "${rEG_ORIG_DIP_IPV6()} = ip6.dst; "
> > +                                 "${rEG_ORIG_TP_DPORT()} = ${protocol}.dst; ct_lb;",
> > +             .external_ids     = map_empty())
> > +    };
> > +
> > +    Flow(.logical_datapath = ls._uuid,
> > +         .stage            = s_SWITCH_IN_PRE_STATEFUL(),
> > +         .priority         = 110,
> > +         .__match          = "${rEGBIT_CONNTRACK_NAT()} == 1",
> > +         .actions          = "ct_lb;",
> > +         .external_ids     = map_empty());
> > +
> > +    Flow(.logical_datapath = ls._uuid,
> > +         .stage            = s_SWITCH_OUT_PRE_STATEFUL(),
> > +         .priority         = 110,
> > +         .__match          = "${rEGBIT_CONNTRACK_NAT()} == 1",
> > +         .actions          = "ct_lb;",
> > +         .external_ids     = map_empty());
> > +
> >      /* If REGBIT_CONNTRACK_DEFRAG is set as 1, then the packets should be
> >       * sent to conntrack for tracking and defragmentation. */
> >      Flow(.logical_datapath = ls._uuid,
> > @@ -2723,66 +2766,7 @@ for (SwitchQoS(.sw = &sw, .qos = &qos)) {
> >      }
> >  }
> >
> > -/* LB rules */
> > -for (&Switch(.ls = ls, .has_lb_vip = has_lb_vip)) {
> > -    /* Ingress and Egress LB Table (Priority 0): Packets are allowed by
> > -     * default.  */
> > -    Flow(.logical_datapath = ls._uuid,
> > -         .stage            = s_SWITCH_IN_LB(),
> > -         .priority         = 0,
> > -         .__match          = "1",
> > -         .actions          = "next;",
> > -         .external_ids     = map_empty());
> > -    Flow(.logical_datapath = ls._uuid,
> > -         .stage            = s_SWITCH_OUT_LB(),
> > -         .priority         = 0,
> > -         .__match          = "1",
> > -         .actions          = "next;",
> > -         .external_ids     = map_empty());
> > -
> > -    if (not ls.load_balancer.is_empty()) {
> > -        for (&SwitchPort(.lsp = lsp at nb::Logical_Switch_Port{.__type = "router"},
> > -                         .json_name = lsp_name,
> > -                         .sw = &Switch{.ls = ls})) {
> > -            Flow(.logical_datapath = ls._uuid,
> > -                 .stage            = s_SWITCH_IN_LB(),
> > -                 .priority         = 65535,
> > -                 .__match          = "ip && inport == ${lsp_name}",
> > -                 .actions          = "next;",
> > -                 .external_ids     = stage_hint(lsp._uuid));
> > -            Flow(.logical_datapath = ls._uuid,
> > -                 .stage            = s_SWITCH_OUT_LB(),
> > -                 .priority         = 65535,
> > -                 .__match          = "ip && outport == ${lsp_name}",
> > -                 .actions          = "next;",
> > -                 .external_ids     = stage_hint(lsp._uuid))
> > -        }
> > -    };
> > -
> > -    if (has_lb_vip) {
> > -        /* Ingress and Egress LB Table (Priority 65534).
> > -         *
> > -         * Send established traffic through conntrack for just NAT. */
> > -        Flow(.logical_datapath = ls._uuid,
> > -             .stage            = s_SWITCH_IN_LB(),
> > -             .priority         = 65534,
> > -             .__match          = "ct.est && !ct.rel && !ct.new && !ct.inv && ct_label.natted == 1",
> > -             .actions          = "${rEGBIT_CONNTRACK_NAT()} = 1; next;",
> > -             .external_ids     = map_empty());
> > -        Flow(.logical_datapath = ls._uuid,
> > -             .stage            = s_SWITCH_OUT_LB(),
> > -             .priority         = 65534,
> > -             .__match          = "ct.est && !ct.rel && !ct.new && !ct.inv && ct_label.natted == 1",
> > -             .actions          = "${rEGBIT_CONNTRACK_NAT()} = 1; next;",
> > -             .external_ids     = map_empty())
> > -    }
> > -}
> > -
> >  /* stateful rules */
> > -relation LbProtocol[string]
> > -LbProtocol["tcp"].
> > -LbProtocol["udp"].
> > -LbProtocol["sctp"].
> >  for (&Switch(.ls = ls)) {
> >      /* Ingress and Egress stateful Table (Priority 0): Packets are
> >       * allowed by default. */
> > @@ -2814,40 +2798,6 @@ for (&Switch(.ls = ls)) {
> >           .priority         = 100,
> >           .__match          = "${rEGBIT_CONNTRACK_COMMIT()} == 1",
> >           .actions          = "ct_commit { ct_label.blocked = 0; }; next;",
> > -         .external_ids     = map_empty());
> > -
> > -    /* If REGBIT_CONNTRACK_NAT is set as 1, then packets should just be sent
> > -     * through nat (without committing).
> > -     *
> > -     * REGBIT_CONNTRACK_COMMIT is set for new connections and
> > -     * REGBIT_CONNTRACK_NAT is set for established connections. So they
> > -     * don't overlap.
> > -     *
> > -     * In the ingress pipeline, also store the original destination IP and
> > -     * transport port to be used when detecting hairpin packets.
> > -     */
> > -    for (LbProtocol[protocol]) {
> > -        Flow(.logical_datapath = ls._uuid,
> > -             .stage            = s_SWITCH_IN_STATEFUL(),
> > -             .priority         = 100,
> > -             .__match          = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip4 && ${protocol}",
> > -             .actions          = "${rEG_ORIG_DIP_IPV4()} = ip4.dst; "
> > -                                 "${rEG_ORIG_TP_DPORT()} = ${protocol}.dst; ct_lb;",
> > -             .external_ids     = map_empty());
> > -        Flow(.logical_datapath = ls._uuid,
> > -             .stage            = s_SWITCH_IN_STATEFUL(),
> > -             .priority         = 100,
> > -             .__match          = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip6 && ${protocol}",
> > -             .actions          = "${rEG_ORIG_DIP_IPV6()} = ip6.dst; "
> > -                                 "${rEG_ORIG_TP_DPORT()} = ${protocol}.dst; ct_lb;",
> > -             .external_ids     = map_empty())
> > -    };
> > -
> > -    Flow(.logical_datapath = ls._uuid,
> > -         .stage            = s_SWITCH_OUT_STATEFUL(),
> > -         .priority         = 100,
> > -         .__match          = "${rEGBIT_CONNTRACK_NAT()} == 1",
> > -         .actions          = "ct_lb;",
> >           .external_ids     = map_empty())
> >  }
> >
> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> > index 96476497df..32b092bcd9 100644
> > --- a/tests/ovn-northd.at
> > +++ b/tests/ovn-northd.at
> > @@ -1201,7 +1201,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw0 lb1
> >
> >  AT_CAPTURE_FILE([sbflows])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*ct_lb' | sed 's/table=..//'], 0, [dnl
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | sed 's/table=..//'], 0, [dnl
> I presume the change s/ct_lb/backends is because you now have multiple
> "ct_lb" actions in the "ls_in_stateful" table?
> >    (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> > @@ -1211,7 +1211,7 @@ wait_row_count Service_Monitor 0
> >
> >  AT_CAPTURE_FILE([sbflows2])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows2 | grep 'priority=120.*ct_lb' | sed 's/table=..//'], [0],
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows2 | grep 'priority=120.*backends' | sed 's/table=..//'], [0],
> >  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> > @@ -1222,7 +1222,7 @@ health_check @hc
> >  wait_row_count Service_Monitor 2
> >  check ovn-nbctl --wait=sb sync
> >
> > -ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt
> > +ovn-sbctl dump-flows sw0 | grep backends | grep priority=120 > lflows.txt
> >  AT_CHECK([cat lflows.txt | sed 's/table=..//'], [0], [dnl
> >    (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> > @@ -1233,7 +1233,7 @@ sm_sw1_p1=$(fetch_column Service_Monitor _uuid logical_port=sw1-p1)
> >
> >  AT_CAPTURE_FILE([sbflows3])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows 3 | grep 'priority=120.*ct_lb' | sed 's/table=..//'], [0],
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows 3 | grep 'priority=120.*backends' | sed 's/table=..//'], [0],
> >  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> > @@ -1244,7 +1244,7 @@ check ovn-nbctl --wait=sb sync
> >
> >  AT_CAPTURE_FILE([sbflows4])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows4 | grep 'priority=120.*ct_lb' | sed 's/table=..//'], [0],
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows4 | grep 'priority=120.*backends' | sed 's/table=..//'], [0],
> >  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);)
> >  ])
> >
> > @@ -1256,7 +1256,7 @@ check ovn-nbctl --wait=sb sync
> >
> >  AT_CAPTURE_FILE([sbflows5])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows5 | grep 'priority=120.*ct_lb'], 1)
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows5 | grep 'priority=120.*backends'], 1)
> >
> >  AT_CAPTURE_FILE([sbflows6])
> >  OVS_WAIT_FOR_OUTPUT(
> > @@ -1273,7 +1273,7 @@ check ovn-nbctl --wait=sb sync
> >
> >  AT_CAPTURE_FILE([sbflows7])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows7 | grep ct_lb | grep priority=120 | sed 's/table=..//'], 0,
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows7 | grep backends | grep priority=120 | sed 's/table=..//'], 0,
> >  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> > @@ -1309,7 +1309,7 @@ wait_row_count Service_Monitor 1 port=1000
> >
> >  AT_CAPTURE_FILE([sbflows9])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows9 | grep ct_lb | grep priority=120 | sed 's/table=..//' | sort],
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows9 | grep backends | grep priority=120 | sed 's/table=..//' | sort],
> >    0,
> >  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);)
> >    (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000);)
> > @@ -1323,7 +1323,7 @@ check ovn-nbctl --wait=sb sync
> >
> >  AT_CAPTURE_FILE([sbflows10])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw0 | tee sbflows10 | grep ct_lb | grep priority=120 | sed 's/table=..//' | sort],
> > +  [ovn-sbctl dump-flows sw0 | tee sbflows10 | grep backends | grep priority=120 | sed 's/table=..//' | sort],
> >    0,
> >  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >    (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);)
> > @@ -1333,7 +1333,7 @@ AS_BOX([Associate lb1 to sw1])
> >  check ovn-nbctl --wait=sb ls-lb-add sw1 lb1
> >  AT_CAPTURE_FILE([sbflows11])
> >  OVS_WAIT_FOR_OUTPUT(
> > -  [ovn-sbctl dump-flows sw1 | tee sbflows11 | grep ct_lb | grep priority=120 | sed 's/table=..//' | sort],
> > +  [ovn-sbctl dump-flows sw1 | tee sbflows11 | grep backends | grep priority=120 | sed 's/table=..//' | sort],
> >    0, [dnl
> >    (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >    (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);)
> > @@ -1393,7 +1393,7 @@ ovn-sbctl set service_monitor $sm_sw1_p1 status=offline
> >  AT_CAPTURE_FILE([sbflows12])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows12 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" | grep priority=120 | sed 's/table=..//'], [0], [dnl
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=6);};)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=5);};)
> >  ])
> >
> >  AT_CLEANUP
> > @@ -1813,13 +1813,13 @@ AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0
> >  ovn-nbctl ls-lb-add sw0 lb1
> >  ovn-nbctl --wait=sb sync
> >  AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl
> > -  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[0]] = 1; next;)
> > +  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[2]] = 1; next;)
> >  ])
> >
> >  ovn-nbctl ls-lb-add sw0 lb2
> >  ovn-nbctl --wait=sb sync
> >  AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl
> > -  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[0]] = 1; next;)
> > +  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[2]] = 1; next;)
> >  ])
> >
> >  lb1_uuid=$(ovn-nbctl --bare --columns _uuid find load_balancer name=lb1)
> > @@ -1828,7 +1828,7 @@ lb2_uuid=$(ovn-nbctl --bare --columns _uuid find load_balancer name=lb2)
> >  ovn-nbctl clear load_balancer $lb1_uuid vips
> >  ovn-nbctl --wait=sb sync
> >  AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl
> > -  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[0]] = 1; next;)
> > +  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[2]] = 1; next;)
> >  ])
> >
> >  ovn-nbctl clear load_balancer $lb2_uuid vips
> > @@ -1841,14 +1841,14 @@ ovn-nbctl set load_balancer $lb2_uuid vips:"10.0.0.11"="10.0.0.4"
> >
> >  ovn-nbctl --wait=sb sync
> >  AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl
> > -  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[0]] = 1; next;)
> > +  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[2]] = 1; next;)
> >  ])
> >
> >  # Now reverse the order of clearing the vip.
> >  ovn-nbctl clear load_balancer $lb2_uuid vips
> >  ovn-nbctl --wait=sb sync
> >  AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl
> > -  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[0]] = 1; next;)
> > +  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[2]] = 1; next;)
> >  ])
> >
> >  ovn-nbctl clear load_balancer $lb1_uuid vips
> > @@ -1900,10 +1900,10 @@ AT_CAPTURE_FILE([sw1flows])
> >
> >  AT_CHECK(
> >    [grep -E 'ls_(in|out)_acl' sw0flows sw1flows | grep pg0 | sort], [0], [dnl
> > -sw0flows:  table=5 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw0flows:  table=9 (ls_in_acl          ), priority=2002 , match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=6); };)
> > -sw1flows:  table=5 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw1flows:  table=9 (ls_in_acl          ), priority=2002 , match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=6); };)
> > +sw0flows:  table=4 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw0flows:  table=9 (ls_in_acl          ), priority=2002 , match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=5); };)
> > +sw1flows:  table=4 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw1flows:  table=9 (ls_in_acl          ), priority=2002 , match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=5); };)
> >  ])
> >
> >  AS_BOX([2])
> > @@ -1916,10 +1916,10 @@ ovn-sbctl dump-flows sw1 > sw1flows2
> >  AT_CAPTURE_FILE([sw1flows2])
> >
> >  AT_CHECK([grep "ls_out_acl" sw0flows2 sw1flows2 | grep pg0 | sort], [0], [dnl
> > -sw0flows2:  table=5 (ls_out_acl         ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw0flows2:  table=5 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw1flows2:  table=5 (ls_out_acl         ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw1flows2:  table=5 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > +sw0flows2:  table=4 (ls_out_acl         ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw0flows2:  table=4 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw1flows2:  table=4 (ls_out_acl         ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw1flows2:  table=4 (ls_out_acl         ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> >  ])
> >
> >  AS_BOX([3])
> > @@ -1932,18 +1932,18 @@ ovn-sbctl dump-flows sw1 > sw1flows3
> >  AT_CAPTURE_FILE([sw1flows3])
> >
> >  AT_CHECK([grep "ls_out_acl" sw0flows3 sw1flows3 | grep pg0 | sort], [0], [dnl
> > -sw0flows3:  table=5 (ls_out_acl         ), priority=2001 , match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
> > -sw0flows3:  table=5 (ls_out_acl         ), priority=2001 , match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
> > -sw0flows3:  table=5 (ls_out_acl         ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), 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=23); };)
> > -sw0flows3:  table=5 (ls_out_acl         ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw0flows3:  table=5 (ls_out_acl         ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), 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=23); };)
> > -sw0flows3:  table=5 (ls_out_acl         ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw1flows3:  table=5 (ls_out_acl         ), priority=2001 , match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
> > -sw1flows3:  table=5 (ls_out_acl         ), priority=2001 , match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
> > -sw1flows3:  table=5 (ls_out_acl         ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), 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=23); };)
> > -sw1flows3:  table=5 (ls_out_acl         ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > -sw1flows3:  table=5 (ls_out_acl         ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), 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=23); };)
> > -sw1flows3:  table=5 (ls_out_acl         ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=23); };)
> > +sw0flows3:  table=4 (ls_out_acl         ), priority=2001 , match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
> > +sw0flows3:  table=4 (ls_out_acl         ), priority=2001 , match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
> > +sw0flows3:  table=4 (ls_out_acl         ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), 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=22); };)
> > +sw0flows3:  table=4 (ls_out_acl         ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw0flows3:  table=4 (ls_out_acl         ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), 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=22); };)
> > +sw0flows3:  table=4 (ls_out_acl         ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw1flows3:  table=4 (ls_out_acl         ), priority=2001 , match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
> > +sw1flows3:  table=4 (ls_out_acl         ), priority=2001 , match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
> > +sw1flows3:  table=4 (ls_out_acl         ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), 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=22); };)
> > +sw1flows3:  table=4 (ls_out_acl         ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> > +sw1flows3:  table=4 (ls_out_acl         ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), 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=22); };)
> > +sw1flows3:  table=4 (ls_out_acl         ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };)
> >  ])
> >  AT_CLEANUP
> >  ])
> > @@ -2083,17 +2083,17 @@ check ovn-nbctl --wait=sb \
> >      -- acl-add ls from-lport 2 "udp" allow-related \
> >      -- acl-add ls to-lport 2 "udp" allow-related
> >  AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | grep 'ct\.' | sort], [0], [dnl
> > -  table=4 (ls_out_acl_hint    ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=3    , match=(!ct.est), action=(reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=5    , match=(!ct.trk), action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > -  table=5 (ls_out_acl         ), priority=1    , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;)
> > -  table=5 (ls_out_acl         ), priority=65535, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;)
> > -  table=5 (ls_out_acl         ), priority=65535, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;)
> > -  table=5 (ls_out_acl         ), priority=65535, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
> > +  table=3 (ls_out_acl_hint    ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=3    , match=(!ct.est), action=(reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=5    , match=(!ct.trk), action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > +  table=4 (ls_out_acl         ), priority=1    , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;)
> > +  table=4 (ls_out_acl         ), priority=65535, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;)
> > +  table=4 (ls_out_acl         ), priority=65535, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;)
> > +  table=4 (ls_out_acl         ), priority=65535, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
> >    table=8 (ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
> >    table=8 (ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
> >    table=8 (ls_in_acl_hint     ), priority=3    , match=(!ct.est), action=(reg0[[9]] = 1; next;)
> > @@ -2115,17 +2115,17 @@ check ovn-nbctl --wait=sb \
> >      -- ls-lb-add ls lb
> >
> >  AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | grep 'ct\.' | sort], [0], [dnl
> > -  table=4 (ls_out_acl_hint    ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=3    , match=(!ct.est), action=(reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=5    , match=(!ct.trk), action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > -  table=4 (ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > -  table=5 (ls_out_acl         ), priority=1    , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;)
> > -  table=5 (ls_out_acl         ), priority=65535, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;)
> > -  table=5 (ls_out_acl         ), priority=65535, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;)
> > -  table=5 (ls_out_acl         ), priority=65535, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
> > +  table=3 (ls_out_acl_hint    ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=3    , match=(!ct.est), action=(reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=5    , match=(!ct.trk), action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > +  table=3 (ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
> > +  table=4 (ls_out_acl         ), priority=1    , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;)
> > +  table=4 (ls_out_acl         ), priority=65535, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;)
> > +  table=4 (ls_out_acl         ), priority=65535, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;)
> > +  table=4 (ls_out_acl         ), priority=65535, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
> >    table=8 (ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
> >    table=8 (ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
> >    table=8 (ls_in_acl_hint     ), priority=3    , match=(!ct.est), action=(reg0[[9]] = 1; next;)
> > @@ -2354,20 +2354,20 @@ check ovn-nbctl \
> >  check ovn-nbctl --wait=sb sync
> >
> >  AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_pre_hairpin | sort], [0], [dnl
> > -  table=14(ls_in_pre_hairpin  ), priority=0    , match=(1), action=(next;)
> > -  table=14(ls_in_pre_hairpin  ), priority=100  , match=(ip && ct.trk), action=(reg0[[6]] = chk_lb_hairpin(); reg0[[12]] = chk_lb_hairpin_reply(); next;)
> > +  table=13(ls_in_pre_hairpin  ), priority=0    , match=(1), action=(next;)
> > +  table=13(ls_in_pre_hairpin  ), priority=100  , match=(ip && ct.trk), action=(reg0[[6]] = chk_lb_hairpin(); reg0[[12]] = chk_lb_hairpin_reply(); next;)
> >  ])
> >
> >  AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort], [0], [dnl
> > -  table=15(ls_in_nat_hairpin  ), priority=0    , match=(1), action=(next;)
> > -  table=15(ls_in_nat_hairpin  ), priority=100  , match=(ip && ct.est && ct.trk && reg0[[6]] == 1), action=(ct_snat;)
> > -  table=15(ls_in_nat_hairpin  ), priority=100  , match=(ip && ct.new && ct.trk && reg0[[6]] == 1), action=(ct_snat_to_vip; next;)
> > -  table=15(ls_in_nat_hairpin  ), priority=90   , match=(ip && reg0[[12]] == 1), action=(ct_snat;)
> > +  table=14(ls_in_nat_hairpin  ), priority=0    , match=(1), action=(next;)
> > +  table=14(ls_in_nat_hairpin  ), priority=100  , match=(ip && ct.est && ct.trk && reg0[[6]] == 1), action=(ct_snat;)
> > +  table=14(ls_in_nat_hairpin  ), priority=100  , match=(ip && ct.new && ct.trk && reg0[[6]] == 1), action=(ct_snat_to_vip; next;)
> > +  table=14(ls_in_nat_hairpin  ), priority=90   , match=(ip && reg0[[12]] == 1), action=(ct_snat;)
> >  ])
> >
> >  AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort], [0], [dnl
> > -  table=16(ls_in_hairpin      ), priority=0    , match=(1), action=(next;)
> > -  table=16(ls_in_hairpin      ), priority=1    , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;)
> > +  table=15(ls_in_hairpin      ), priority=0    , match=(1), action=(next;)
> > +  table=15(ls_in_hairpin      ), priority=1    , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;)
> >  ])
> >
> >  AT_CLEANUP
> > @@ -2950,4 +2950,135 @@ wait_row_count FDB 0
> >  ovn-sbctl list FDB
> >
> >  AT_CLEANUP
> > -])
> > \ No newline at end of file
> > +])
> > +
> > +OVN_FOR_EACH_NORTHD([
> > +AT_SETUP([ovn -- LS load balancer logical flows])
> > +ovn_start
> > +
> > +check ovn-nbctl \
> > +    -- ls-add sw0 \
> > +    -- lb-add lb0 10.0.0.10:80 10.0.0.4:8080 \
> > +    -- ls-lb-add sw0 lb0
> > +
> > +check ovn-nbctl lr-add lr0
> > +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
> > +check ovn-nbctl lsp-add sw0 sw0-lr0
> > +check ovn-nbctl lsp-set-type sw0-lr0 router
> > +check ovn-nbctl lsp-set-addresses sw0-lr0 00:00:00:00:ff:01
> > +check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
> > +
> > +check ovn-nbctl --wait=sb sync
> > +
> > +check_stateful_flows() {
> > +    ovn-sbctl dump-flows sw0 > sw0flows
> > +    AT_CAPTURE_FILE([sw0flows])
> > +
> > +    AT_CHECK([grep "ls_in_pre_lb" sw0flows | sort], [0], [dnl
> > +  table=6 (ls_in_pre_lb       ), priority=0    , match=(1), action=(next;)
> > +  table=6 (ls_in_pre_lb       ), priority=100  , match=(ip), action=(reg0[[2]] = 1; next;)
> > +  table=6 (ls_in_pre_lb       ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
> > +  table=6 (ls_in_pre_lb       ), priority=110  , match=(ip && inport == "sw0-lr0"), action=(next;)
> > +  table=6 (ls_in_pre_lb       ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
> > +])
> > +
> > +    AT_CHECK([grep "ls_in_pre_stateful" sw0flows | sort], [0], [dnl
> > +  table=7 (ls_in_pre_stateful ), priority=0    , match=(1), action=(next;)
> > +  table=7 (ls_in_pre_stateful ), priority=100  , match=(reg0[[0]] == 1), action=(ct_next;)
> > +  table=7 (ls_in_pre_stateful ), priority=110  , match=(reg0[[2]] == 1), action=(ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && sctp), action=(reg1 = ip4.dst; reg2[[0..15]] = sctp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && tcp), action=(reg1 = ip4.dst; reg2[[0..15]] = tcp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && udp), action=(reg1 = ip4.dst; reg2[[0..15]] = udp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && sctp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = sctp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && tcp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = tcp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = udp.dst; ct_lb;)
> > +])
> > +
> > +    AT_CHECK([grep "ls_in_lb" sw0flows | sort], [0], [])
> > +
> > +    AT_CHECK([grep "ls_in_stateful" sw0flows | sort], [0], [dnl
> > +  table=12(ls_in_stateful     ), priority=0    , match=(1), action=(next;)
> > +  table=12(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
> > +  table=12(ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.4:8080);)
> > +])
> > +
> > +    AT_CHECK([grep "ls_out_pre_lb" sw0flows | sort], [0], [dnl
> > +  table=0 (ls_out_pre_lb      ), priority=0    , match=(1), action=(next;)
> > +  table=0 (ls_out_pre_lb      ), priority=100  , match=(ip), action=(reg0[[2]] = 1; next;)
> > +  table=0 (ls_out_pre_lb      ), priority=110  , match=(eth.src == $svc_monitor_mac), action=(next;)
> > +  table=0 (ls_out_pre_lb      ), priority=110  , match=(ip && outport == "sw0-lr0"), action=(next;)
> > +  table=0 (ls_out_pre_lb      ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
> > +])
> > +
> > +    AT_CHECK([grep "ls_out_pre_stateful" sw0flows | sort], [0], [dnl
> > +  table=2 (ls_out_pre_stateful), priority=0    , match=(1), action=(next;)
> > +  table=2 (ls_out_pre_stateful), priority=100  , match=(reg0[[0]] == 1), action=(ct_next;)
> > +  table=2 (ls_out_pre_stateful), priority=110  , match=(reg0[[2]] == 1), action=(ct_lb;)
> > +])
> > +
> > +    AT_CHECK([grep "ls_out_lb" sw0flows | sort], [0], [])
>
> This might be a bit cryptic in the future ("what is the ls_out_lb
> table?!?") as it will not exist. Do we really need this check here? If
> so, maybe add  a comment to explain why it is here.

I will remove it in v4.

> > +
> > +    AT_CHECK([grep "ls_out_stateful" sw0flows | sort], [0], [dnl
> > +  table=7 (ls_out_stateful    ), priority=0    , match=(1), action=(next;)
> > +  table=7 (ls_out_stateful    ), priority=100  , match=(reg0[[1]] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
> > +])
> > +}
> > +
> > +check_stateful_flows
> > +
> > +# Add few ACLs
> > +check ovn-nbctl --wait=sb acl-add sw0 from-lport 1002 "ip4 && tcp && tcp.dst == 80" allow-related
> > +check ovn-nbctl --wait=sb acl-add sw0 to-lport 1002 "ip4 && tcp && tcp.src == 80" drop
> > +
> > +check_stateful_flows
> > +
> > +# Remove load balancer from sw0
> > +check ovn-nbctl --wait=sb ls-lb-del sw0 lb0
> > +
> > +ovn-sbctl dump-flows sw0 > sw0flows
> > +AT_CAPTURE_FILE([sw0flows])
> > +
> > +AT_CHECK([grep "ls_in_pre_lb" sw0flows | sort], [0], [dnl
> > +  table=6 (ls_in_pre_lb       ), priority=0    , match=(1), action=(next;)
> > +  table=6 (ls_in_pre_lb       ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
> > +  table=6 (ls_in_pre_lb       ), priority=110  , match=(ip && inport == "sw0-lr0"), action=(next;)
> > +  table=6 (ls_in_pre_lb       ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
> > +])
> > +
> > +AT_CHECK([grep "ls_in_pre_stateful" sw0flows | sort], [0], [dnl
> > +  table=7 (ls_in_pre_stateful ), priority=0    , match=(1), action=(next;)
> > +  table=7 (ls_in_pre_stateful ), priority=100  , match=(reg0[[0]] == 1), action=(ct_next;)
> > +  table=7 (ls_in_pre_stateful ), priority=110  , match=(reg0[[2]] == 1), action=(ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && sctp), action=(reg1 = ip4.dst; reg2[[0..15]] = sctp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && tcp), action=(reg1 = ip4.dst; reg2[[0..15]] = tcp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && udp), action=(reg1 = ip4.dst; reg2[[0..15]] = udp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && sctp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = sctp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && tcp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = tcp.dst; ct_lb;)
> > +  table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = udp.dst; ct_lb;)
> > +])
> > +
> > +AT_CHECK([grep "ls_in_stateful" sw0flows | sort], [0], [dnl
> > +  table=12(ls_in_stateful     ), priority=0    , match=(1), action=(next;)
> > +  table=12(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
> > +])
> > +
> > +AT_CHECK([grep "ls_out_pre_lb" sw0flows | sort], [0], [dnl
> > +  table=0 (ls_out_pre_lb      ), priority=0    , match=(1), action=(next;)
> > +  table=0 (ls_out_pre_lb      ), priority=110  , match=(eth.src == $svc_monitor_mac), action=(next;)
> > +  table=0 (ls_out_pre_lb      ), priority=110  , match=(ip && outport == "sw0-lr0"), action=(next;)
> It seems like this^ flow is not described in the man page for
> ovn-northd. You did not introduce this but maybe you could update it by
> coping the description from the Ingress table.

If you see the documentation, you would notice that such flows which
have corresponding
flows in the ingress pipeline are not explictly documented.  The
documentation generally says
"This table is similar to the ingress table".

So I will AS IS now.

Thanks
Numan

> > +  table=0 (ls_out_pre_lb      ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
> > +])
> > +
> > +AT_CHECK([grep "ls_out_pre_stateful" sw0flows | sort], [0], [dnl
> > +  table=2 (ls_out_pre_stateful), priority=0    , match=(1), action=(next;)
> > +  table=2 (ls_out_pre_stateful), priority=100  , match=(reg0[[0]] == 1), action=(ct_next;)
> > +  table=2 (ls_out_pre_stateful), priority=110  , match=(reg0[[2]] == 1), action=(ct_lb;)
> > +])
> > +
> > +AT_CHECK([grep "ls_out_stateful" sw0flows | sort], [0], [dnl
> > +  table=7 (ls_out_stateful    ), priority=0    , match=(1), action=(next;)
> > +  table=7 (ls_out_stateful    ), priority=100  , match=(reg0[[1]] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
> > +])
> > +
> > +AT_CLEANUP
> > +])
> > diff --git a/tests/ovn.at b/tests/ovn.at
> > index 73cc8bf025..d7da84459c 100644
> > --- a/tests/ovn.at
> > +++ b/tests/ovn.at
> > @@ -14088,16 +14088,16 @@ check ovn-nbctl acl-add ls1 to-lport 3 'ip4.src==10.0.0.1' allow
> >  check ovn-nbctl --wait=hv sync
> >
> >  # Check OVS flows, the less restrictive flows should have been installed.
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \
> >      grep "priority=1003" | \
> >      sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl
> > - table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> > + table=44, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> >  ])
> >
> >  # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed.
> > @@ -14132,16 +14132,16 @@ check ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1 || ip4.src==10.0.0.1'
> >  check ovn-nbctl --wait=hv sync
> >
> >  # Check OVS flows, the second less restrictive allow ACL should have been installed.
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \
> >      grep "priority=1003" | \
> >      sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl
> > - table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> > + table=44, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> >  ])
> >
> >  # Remove the less restrictive allow ACL.
> > @@ -14149,16 +14149,16 @@ check ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1'
> >  check ovn-nbctl --wait=hv sync
> >
> >  # Check OVS flows, the 10.0.0.1 conjunction should have been reinstalled.
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \
> >      grep "priority=1003" | \
> >      sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl
> > - table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> > + table=44, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> >  ])
> >
> >  # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed.
> > @@ -14188,16 +14188,16 @@ check ovn-nbctl acl-add ls1 to-lport 3 'ip4.src==10.0.0.1' allow
> >  check ovn-nbctl --wait=hv sync
> >
> >  # Check OVS flows, the less restrictive flows should have been installed.
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \
> >     grep "priority=1003" | \
> >     sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl
> > - table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> > + table=44, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> >  ])
> >
> >  # Add another ACL that overlaps with the existing less restrictive ones.
> > @@ -14208,19 +14208,19 @@ check ovn-nbctl --wait=hv sync
> >  # with an additional conjunction action.
> >  #
> >  # New non-conjunctive flows should be added to match on 'udp'.
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \
> >     grep "priority=1003" | \
> >     sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl
> > - table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,conj_id=4,ip,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46)
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(),conjunction()
> > - table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> > - table=45, priority=1003,udp,metadata=0x1 actions=resubmit(,46)
> > - table=45, priority=1003,udp6,metadata=0x1 actions=resubmit(,46)
> > + table=44, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,conj_id=4,ip,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45)
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(),conjunction()
> > + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction()
> > + table=44, priority=1003,udp,metadata=0x1 actions=resubmit(,45)
> > + table=44, priority=1003,udp6,metadata=0x1 actions=resubmit(,45)
> >  ])
> >
> >  OVN_CLEANUP([hv1])
> > @@ -15549,7 +15549,7 @@ wait_for_ports_up 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=30,dl_src=f0:00:00:00:00:03,dl_dst=a0:10:00:00:00:01 | \
> > +table=29,dl_src=f0:00:00:00:00:03,dl_dst=a0:10:00:00:00:01 | \
> >  grep -c "actions=drop"], [0], [1
> >  ])
> >
> > @@ -19994,7 +19994,14 @@ AT_CAPTURE_FILE([sbflows])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows > sbflows
> >     ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 | sed 's/table=..//'], 0,
> > -  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");)
> > +  [dnl
> > +  (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && sctp), action=(reg1 = ip4.dst; reg2[[0..15]] = sctp.dst; ct_lb;)
> > +  (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && tcp), action=(reg1 = ip4.dst; reg2[[0..15]] = tcp.dst; ct_lb;)
> > +  (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4 && udp), action=(reg1 = ip4.dst; reg2[[0..15]] = udp.dst; ct_lb;)
> > +  (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && sctp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = sctp.dst; ct_lb;)
> > +  (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && tcp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = tcp.dst; ct_lb;)
> > +  (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = udp.dst; ct_lb;)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");)
> >  ])
> >
> >  AT_CAPTURE_FILE([sbflows2])
> > @@ -22731,7 +22738,7 @@ check ovn-nbctl --wait=hv sync
> >  # wait_conj_id_count COUNT ["ID COUNT [MATCH]"]...
> >  #
> >  # Waits until COUNT flows matching against conj_id appear in the
> > -# table 45 on hv1's br-int bridge.  Makes the flows available in
> > +# table 44 on hv1's br-int bridge.  Makes the flows available in
> >  # "hv1flows", which will be logged on error.
> >  #
> >  # In addition, for each quoted "ID COUNT" or "ID COUNT MATCH",
> > @@ -22748,7 +22755,7 @@ wait_conj_id_count() {
> >    echo "waiting for $1 conj_id flows..."
> >    OVS_WAIT_FOR_OUTPUT_UNQUOTED(
> >      [ovs-ofctl dump-flows br-int > hv1flows
> > -     grep table=45 hv1flows | grep -c conj_id],
> > +     grep table=44 hv1flows | grep -c conj_id],
> >      [$retval], [$1
> >  ])
> >
> > @@ -22757,7 +22764,7 @@ wait_conj_id_count() {
> >      set -- $arg; id=$1 count=$2 match=$3
> >      echo "checking that there are $count ${match:+$match }flows with conj_id=$id..."
> >      AT_CHECK_UNQUOTED(
> > -      [grep table=45 hv1flows | grep "$match" | grep -c conj_id=$id],
> > +      [grep table=44 hv1flows | grep "$match" | grep -c conj_id=$id],
> >        [0], [$count
> >  ])
> >    done
> > @@ -22782,8 +22789,8 @@ wait_conj_id_count 1 "3 1 udp"
> >  AS_BOX([Add back the tcp ACL.])
> >  check ovn-nbctl --wait=hv acl-add pg0 to-lport 1002 "outport == @pg0 && ip4 && tcp.dst >= 80 && tcp.dst <= 82" allow
> >  wait_conj_id_count 2 "3 1 udp" "4 1 tcp"
> > -AT_CHECK([test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=45 | grep udp | grep -c "conj_id=3")])
> > -AT_CHECK([test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=45 | grep tcp | grep -c "conj_id=4")])
> > +AT_CHECK([test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=44 | grep udp | grep -c "conj_id=3")])
> > +AT_CHECK([test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=44 | grep tcp | grep -c "conj_id=4")])
> >
> >  AS_BOX([Add another tcp ACL.])
> >  check ovn-nbctl --wait=hv acl-add pg0 to-lport 1002 "outport == @pg0 && inport == @pg0 && ip4 && tcp.dst >= 84 && tcp.dst <= 86" allow
> > @@ -24750,43 +24757,43 @@ AT_CHECK([kill -0 $(cat hv1/ovn-controller.pid)])
> >  check ovn-nbctl --wait=hv sync
> >
> >  # Check OVS flows are installed properly.
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \
> >      grep "priority=2002" | grep conjunction | \
> >      sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x10/0xfff0 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x100/0xff00 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x1000/0xf000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2/0xfffe actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x20/0xffe0 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x200/0xfe00 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2000/0xe000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4/0xfffc actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x40/0xffc0 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x400/0xfc00 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4000/0xc000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8/0xfff8 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x80/0xff80 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x800/0xf800 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8000/0x8000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=1 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x100/0x100,reg15=0x3,metadata=0x1,nw_src=192.168.47.3 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x10/0xfff0 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x100/0xff00 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x1000/0xf000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2/0xfffe actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x20/0xffe0 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x200/0xfe00 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2000/0xe000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4/0xfffc actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x40/0xffc0 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x400/0xfc00 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4000/0xc000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8/0xfff8 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x80/0xff80 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x800/0xf800 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8000/0x8000 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=1 actions=conjunction()
> > - table=45, priority=2002,udp,reg0=0x80/0x80,reg15=0x3,metadata=0x1,nw_src=192.168.47.3 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x10/0xfff0 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x100/0xff00 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x1000/0xf000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2/0xfffe actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x20/0xffe0 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x200/0xfe00 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2000/0xe000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4/0xfffc actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x40/0xffc0 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x400/0xfc00 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4000/0xc000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8/0xfff8 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x80/0xff80 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x800/0xf800 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8000/0x8000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.3,tp_dst=1 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x100/0x100,reg15=0x3,metadata=0x1,nw_src=192.168.47.3 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x10/0xfff0 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x100/0xff00 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x1000/0xf000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2/0xfffe actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x20/0xffe0 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x200/0xfe00 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x2000/0xe000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4/0xfffc actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x40/0xffc0 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x400/0xfc00 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x4000/0xc000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8/0xfff8 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x80/0xff80 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x800/0xf800 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=0x8000/0x8000 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.3,tp_dst=1 actions=conjunction()
> > + table=44, priority=2002,udp,reg0=0x80/0x80,reg15=0x3,metadata=0x1,nw_src=192.168.47.3 actions=conjunction()
> >  ])
> >
> >  OVN_CLEANUP([hv1])
> >
>
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>


More information about the dev mailing list