On Thu, Feb 24, 2022 at 11:17 AM Mark Michelson <[email protected]> wrote:
>
> On 2/23/22 19:39, Numan Siddique wrote:
> > On Wed, Feb 23, 2022 at 7:22 AM Frode Nordahl
> > <[email protected]> wrote:
> >>
> >> Hello Mark,
> >>
> >> This overall looks great, it also looks like you addressed Numan's
> >> comments from the previous iteration.
> >>
> >> I have added a nit in-line to save you from a conversation with 0-day
> >> / checkpatch.
> >>
> >> In addition to reviewing I took your patch for a ride and it works as 
> >> expected.
> >>
> >> Would you perhaps want to re-base?
> >>
> >>
> >> On Fri, Feb 11, 2022 at 10:47 PM Mark Michelson <[email protected]> 
> >> wrote:
> >>>
> >>> It can be desirable for replies to stateful ACLs to be logged. And in
> >>> some cases, it can actually be a bit confusing why they aren't logged.
> >>
> >> I would agree, this is a nice addition!
> >>
> >>> Consider a situation where a port group called "port_group" exists and
> >>> logical switch ports swp1 and swp2 belong to it. We create the following
> >>> ACL, where logging is enabled:
> >>>
> >>> from-lport 100 'inport == @port_group' allow-stateless
> >>>
> >>> swp1 sends traffic to swp2 and swp2 responds within the same connection.
> >>> In this case, the logs will show both the packets from swp1 to swp2, as
> >>> well as the response packets from swp2 to swp1.
> >>>
> >>> Now change the ACL:
> >>>
> >>> from-lport 100 'inport == @port_group' allow-related
> >>>
> >>> Now with the same traffic pattern, the packets from swp1 to swp2 are
> >>> logged, but the packets from swp2 to swp1 are not. Why is that?
> >>>
> >>> The reason is that as a shortcut, when stateful ACLs are used, a single
> >>> priority 65532 flow is programmed to allow reply traffic to pass. When
> >>> no stateful ACL is present, the reply traffic is at the mercy of the
> >>> stateless ACL on the reply. Therefore, with the stateful ACL, the reply
> >>> traffic is not actually hitting an ACL but is let through by default,
> >>> but with the stateless ACL, the reply traffic does hit the ACL
> >>> evaluation, so the reply traffic is logged.
> >>>
> >>> This change adds a feature that allows for reply traffic to be
> >>> optionally logged for stateful ACLs, therefore allowing for the behavior
> >>> to be similar for both ACL types. Since logging reply traffic requires
> >>> adding more flows, it is not enabled by default. In order to have reply
> >>> traffic logged, the ACL must have logging enabled, be stateful, have a
> >>> label, and have the new log_related column set to true,
> >>>
> >>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2031150
> >>>
> >>> Signed-off-by: Mark Michelson <[email protected]>
> >
> > Hi Mark,
> >
> > Thanks for addressing the comments in v3.
> >
> > The patch LGTM.  Before providing the Ack,  I've one question.
> > Why do we need to set the acl label in order to make use of this feature ?
>
> The label is how we identify which ACL to log when we process the reply.
> I wasn't able to think of a more foolproof method of matching the reply
> traffic to a specific ACL. If you have an idea that doesn't involve
> using the ACL label, I'd be happy to try it out. The only thing I could
> think of is if ovn-northd created its own "internal" label on each ACL
> that is unrelated to the user-set label. Then this could be applied to
> the CT label.

Ok.  Got it.  Thanks for the explanation.

I think it's reasonable for CMS to configure the label if it wants to
enable the logging for the reply traffic.

Acked-by: Numan Siddique <[email protected]>

I think it would help if you could include the above explanation
somewhere, either in documentation or as a code comment.

Thanks
Numan

>
> >
> > Numan
> >
> >>> ---
> >>> v2 -> v3:
> >>> * Added item to NEWS
> >>> * Added flow documentation to ovn-northd.8.xml
> >>> * Added "options" column to ACL instead of having a dedicated
> >>>    log_related column
> >>> ---
> >>>   NEWS                    |   4 +
> >>>   northd/northd.c         |  42 +++++
> >>>   northd/ovn-northd.8.xml |   8 +-
> >>>   ovn-nb.ovsschema        |   9 +-
> >>>   ovn-nb.xml              |  15 ++
> >>>   tests/automake.mk       |   3 +-
> >>>   tests/check_acl_log.py  | 107 ++++++++++++
> >>>   tests/ovn-northd.at     | 253 ++++++++++++++++++++++++++++
> >>>   tests/system-ovn.at     | 359 ++++++++++++++++++++++++++++++++++++++++
> >>>   9 files changed, 796 insertions(+), 4 deletions(-)
> >>>   create mode 100644 tests/check_acl_log.py
> >>>
> >>> diff --git a/NEWS b/NEWS
> >>> index 194557410..5435aa606 100644
> >>> --- a/NEWS
> >>> +++ b/NEWS
> >>> @@ -1,5 +1,9 @@
> >>>   Post v21.12.0
> >>>   -------------
> >>> +  - ACLs now have an "options" column for configuration of extra options.
> >>> +  - A new ACL option, "log-related" has been added that allows for reply 
> >>> and
> >>> +    related traffic to be logged for an ACL in addition to the traffic 
> >>> that
> >>> +    directly matches the ACL.
> >>>
> >>>   OVN v21.12.0 - 22 Dec 2021
> >>>   --------------------------
> >>> diff --git a/northd/northd.c b/northd/northd.c
> >>> index 22e783ff6..f545891f8 100644
> >>> --- a/northd/northd.c
> >>> +++ b/northd/northd.c
> >>> @@ -6242,6 +6242,48 @@ consider_acl(struct hmap *lflows, struct 
> >>> ovn_datapath *od,
> >>>                                       acl->priority + OVN_ACL_PRI_OFFSET,
> >>>                                       ds_cstr(match), ds_cstr(actions),
> >>>                                       &acl->header_);
> >>> +
> >>> +            /* Related and reply traffic are universally allowed by 
> >>> priority
> >>> +             * 65532 flows created in build_acls(). If logging is 
> >>> enabled on
> >>> +             * the ACL, then we need to ensure that the related and reply
> >>> +             * traffic is logged, so we install a slightly 
> >>> higher-priority
> >>> +             * flow that matches the ACL, allows the traffic, and logs 
> >>> it.
> >>> +             */
> >>> +            bool log_related = smap_get_bool(&acl->options, 
> >>> "log-related", false);
> >>
> >> Checkpatch will have opinions on the length of this line.
> >>
> >>> +            if (acl->log && acl->label && log_related) {
> >>> +                /* Related/reply flows need to be set on the opposite 
> >>> pipeline
> >>> +                 * from where the ACL itself is set.
> >>> +                 */
> >>> +                enum ovn_stage log_related_stage = ingress ?
> >>> +                    S_SWITCH_OUT_ACL :
> >>> +                    S_SWITCH_IN_ACL;
> >>> +                ds_clear(match);
> >>> +                ds_clear(actions);
> >>> +
> >>> +                ds_put_format(match, "ct.est && !ct.rel && !ct.new%s && "
> >>> +                              "ct.rpl && ct_label.blocked == 0 && "
> >>> +                              "ct_label.label == %" PRId64,
> >>> +                              use_ct_inv_match ? " && !ct.inv" : "",
> >>> +                              acl->label);
> >>> +                build_acl_log(actions, acl, meter_groups);
> >>> +                ds_put_cstr(actions, "next;");
> >>> +                ovn_lflow_add_with_hint(lflows, od, log_related_stage,
> >>> +                                        UINT16_MAX - 2,
> >>> +                                        ds_cstr(match), ds_cstr(actions),
> >>> +                                        &acl->header_);
> >>> +
> >>> +                ds_clear(match);
> >>> +                ds_put_format(match, "!ct.est && ct.rel && !ct.new%s && "
> >>> +                                     "ct_label.blocked == 0 && "
> >>> +                                     "ct_label.label == %" PRId64,
> >>> +                                     use_ct_inv_match ? " && !ct.inv" : 
> >>> "",
> >>> +                                     acl->label);
> >>> +                ovn_lflow_add_with_hint(lflows, od, log_related_stage,
> >>> +                                        UINT16_MAX - 2,
> >>> +                                        ds_cstr(match), ds_cstr(actions),
> >>> +                                        &acl->header_);
> >>> +            }
> >>> +
> >>>           }
> >>>       } else if (!strcmp(acl->action, "drop")
> >>>                  || !strcmp(acl->action, "reject")) {
> >>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> >>> index 79f35bc16..cfe694831 100644
> >>> --- a/northd/ovn-northd.8.xml
> >>> +++ b/northd/ovn-northd.8.xml
> >>> @@ -746,7 +746,10 @@
> >>>           go through the flows that implement the currently defined
> >>>           policy based on ACLs.  If a connection is no longer allowed by
> >>>           policy, <code>ct_label.blocked</code> will get set and packets 
> >>> in the
> >>> -        reply direction will no longer be allowed, either.
> >>> +        reply direction will no longer be allowed, either. If ACL logging
> >>> +        and logging of related packets is enabled, then a companion 
> >>> priority-
> >>> +        65533 flow will be installed that accomplishes the same thing but
> >>> +        also logs the traffic.
> >>>         </li>
> >>>
> >>>         <li>
> >>> @@ -754,6 +757,9 @@
> >>>           related to a committed flow in the connection tracker (e.g., an
> >>>           ICMP Port Unreachable from a non-listening UDP port), as long
> >>>           as the committed flow does not have 
> >>> <code>ct_label.blocked</code> set.
> >>> +        If ACL logging and logging of related packets is enabled, then a
> >>> +        companion priority-65533 flow will be installed that 
> >>> accomplishes the
> >>> +        same thing but also logs the traffic.
> >>>         </li>
> >>>
> >>>         <li>
> >>> diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
> >>> index 55977339a..530028018 100644
> >>> --- a/ovn-nb.ovsschema
> >>> +++ b/ovn-nb.ovsschema
> >>> @@ -1,7 +1,7 @@
> >>>   {
> >>>       "name": "OVN_Northbound",
> >>> -    "version": "5.34.1",
> >>> -    "cksum": "2177334725 30782",
> >>> +    "version": "5.35.0",
> >>> +    "cksum": "131378816 30999",
> >>>       "tables": {
> >>>           "NB_Global": {
> >>>               "columns": {
> >>
> >> This part is now out of date with the main branch, but you know the
> >> drill for that.
> >>
> >>> @@ -262,6 +262,11 @@
> >>>                   "label": {"type": {"key": {"type": "integer",
> >>>                                              "minInteger": 0,
> >>>                                              "maxInteger": 4294967295}}},
> >>> +                "options": {
> >>> +                     "type": {"key": "string",
> >>> +                              "value": "string",
> >>> +                              "min": 0,
> >>> +                              "max": "unlimited"}},
> >>>                   "external_ids": {
> >>>                       "type": {"key": "string", "value": "string",
> >>>                                "min": 0, "max": "unlimited"}}},
> >>> diff --git a/ovn-nb.xml b/ovn-nb.xml
> >>> index 6a6972856..645c75e3c 100644
> >>> --- a/ovn-nb.xml
> >>> +++ b/ovn-nb.xml
> >>> @@ -2064,6 +2064,21 @@
> >>>       </group>
> >>>
> >>>       <group title="Common Columns">
> >>> +      <column name="options">
> >>> +        This column provides general key/value settings. The supported
> >>> +        options are described individually below.
> >>> +      </column>
> >>> +
> >>> +      <group title="ACL configuration options">
> >>> +        <column name="options" key="log-related">
> >>> +          If set to <code>true</code>, then log when reply or related
> >>> +          traffic is admitted from a stateful ACL. In order for this
> >>> +          option to function, the <ref column="log"/> option must be
> >>> +          set to <code>true</code> and a <ref column="label"/> must
> >>> +          be set.
> >>> +        </column>
> >>> +      </group>
> >>> +
> >>>         <column name="external_ids">
> >>>           See <em>External IDs</em> at the beginning of this document.
> >>>         </column>
> >>> diff --git a/tests/automake.mk b/tests/automake.mk
> >>> index a08dfa632..a5934d2b9 100644
> >>> --- a/tests/automake.mk
> >>> +++ b/tests/automake.mk
> >>> @@ -270,7 +270,8 @@ tests_ovstest_LDADD = $(OVS_LIBDIR)/daemon.lo \
> >>>   CHECK_PYFILES = \
> >>>          tests/test-l7.py \
> >>>          tests/uuidfilt.py \
> >>> -       tests/test-tcp-rst.py
> >>> +       tests/test-tcp-rst.py \
> >>> +       tests/check_acl_log.py
> >>>
> >>>   EXTRA_DIST += $(CHECK_PYFILES)
> >>>   PYCOV_CLEAN_FILES += $(CHECK_PYFILES:.py=.py,cover) .coverage
> >>> diff --git a/tests/check_acl_log.py b/tests/check_acl_log.py
> >>> new file mode 100644
> >>> index 000000000..1dd9630c0
> >>> --- /dev/null
> >>> +++ b/tests/check_acl_log.py
> >>> @@ -0,0 +1,107 @@
> >>> +#!/usr/bin/env python3
> >>> +import argparse
> >>> +import string
> >>> +
> >>> +
> >>> +def strip(val):
> >>> +    """Strip whitespace and quotation marks from val"""
> >>> +    return val.strip(f"{string.whitespace}\"'")
> >>> +
> >>> +
> >>> +def parse_acl_log(line):
> >>> +    """Convert an ACL log string into a dict"""
> >>> +    # First cut off the logging preamble.
> >>> +    # We're assuming the default log format.
> >>> +    acl_log = {}
> >>> +    _, _, details = line.rpartition("|")
> >>> +
> >>> +    # acl_details are things like the acl name, direction,
> >>> +    # verdict, and severity. packet_details are things like
> >>> +    # the protocol, addresses, and ports of the packet being
> >>> +    # logged.
> >>> +    acl_details, _, packet_details = details.partition(":")
> >>> +    for datum in acl_details.split(","):
> >>> +        name, _, value = datum.rpartition("=")
> >>> +        acl_log[strip(name)] = strip(value)
> >>> +
> >>> +    for datum in packet_details.split(","):
> >>> +        name, _, value = datum.rpartition("=")
> >>> +        if not name:
> >>> +            # The protocol is not preceded by "protocol="
> >>> +            # so we need to add it manually.
> >>> +            name = "protocol"
> >>> +        acl_log[strip(name)] = strip(value)
> >>> +
> >>> +    return acl_log
> >>> +
> >>> +
> >>> +def get_acl_log(entry_num=1):
> >>> +    with open("ovn-controller.log", "r") as controller_log:
> >>> +        acl_logs = [line for line in controller_log if "acl_log" in line]
> >>> +        try:
> >>> +            return acl_logs[entry_num - 1]
> >>> +        except IndexError:
> >>> +            print(
> >>> +                f"There were not {entry_num} acl_log entries, \
> >>> +                only {len(acl_logs)}"
> >>> +            )
> >>> +            exit(1)
> >>> +
> >>> +
> >>> +def add_parser_args(parser):
> >>> +    parser.add_argument("--entry-num", type=int, default=1)
> >>> +
> >>> +    # There are other possible things that can be in an ACL log,
> >>> +    # and if we need those in the future, we can add them later.
> >>> +    parser.add_argument("--name")
> >>> +    parser.add_argument("--verdict")
> >>> +    parser.add_argument("--severity")
> >>> +    parser.add_argument("--protocol")
> >>> +    parser.add_argument("--vlan_tci")
> >>> +    parser.add_argument("--dl_src")
> >>> +    parser.add_argument("--dl_dst")
> >>> +    parser.add_argument("--nw_src")
> >>> +    parser.add_argument("--nw_dst")
> >>> +    parser.add_argument("--nw_tos")
> >>> +    parser.add_argument("--nw_ecn")
> >>> +    parser.add_argument("--nw_ttl")
> >>> +    parser.add_argument("--icmp_type")
> >>> +    parser.add_argument("--icmp_code")
> >>> +    parser.add_argument("--tp_src")
> >>> +    parser.add_argument("--tp_dst")
> >>> +    parser.add_argument("--tcp_flags")
> >>> +    parser.add_argument("--ipv6_src")
> >>> +    parser.add_argument("--ipv6_dst")
> >>> +
> >>> +
> >>> +def main():
> >>> +    parser = argparse.ArgumentParser()
> >>> +    add_parser_args(parser)
> >>> +    args = parser.parse_args()
> >>> +
> >>> +    acl_log = get_acl_log(args.entry_num)
> >>> +    parsed_log = parse_acl_log(acl_log)
> >>> +
> >>> +    # Express command line arguments as a dict, omitting any arguments 
> >>> that
> >>> +    # were not provided by the user.
> >>> +    expected = {k: v for k, v in vars(args).items() if v is not None}
> >>> +    del expected["entry_num"]
> >>> +
> >>> +    for key, val in expected.items():
> >>> +        try:
> >>> +            if parsed_log[key] != val:
> >>> +                print(
> >>> +                    f"Expected log {key}={val} but got 
> >>> {key}={parsed_log[key]} \
> >>> +                    in:\n\t'{acl_log}"
> >>> +                )
> >>> +                exit(1)
> >>> +        except KeyError:
> >>> +            print(
> >>> +                f"Expected log {key}={val} but {key} does not exist \
> >>> +                in:\n\t'{acl_log}'"
> >>> +            )
> >>> +            exit(1)
> >>> +
> >>> +
> >>> +if __name__ == "__main__":
> >>> +    main()
> >>
> >> Love the elaborate validation script.
> >>
> >> --
> >> Frode Nordahl
> >>
> >>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> >>> index 652903761..999c31335 100644
> >>> --- a/tests/ovn-northd.at
> >>> +++ b/tests/ovn-northd.at
> >>> @@ -5888,5 +5888,258 @@ AT_CHECK([grep -e "(lr_in_ip_routing   
> >>> ).*outport" lr0flows | sed 's/table=../ta
> >>>     table=??(lr_in_ip_routing   ), priority=97   , match=(reg7 == 2 && 
> >>> ip4.dst == 1.1.1.1/32), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
> >>> 192.168.0.20; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = 
> >>> "lrp0"; flags.loopback = 1; next;)
> >>>   ])
> >>>
> >>> +AT_CLEANUP
> >>> +])
> >>> +
> >>> +OVN_FOR_EACH_NORTHD([
> >>> +AT_SETUP([ACL log replies -- flows])
> >>> +
> >>> +set_acl_options() {
> >>> +    local acl_name=$1
> >>> +    local label=$2
> >>> +    local log_related=$3
> >>> +
> >>> +    local acl_uuid=$(fetch_column nb:ACL _uuid name=$acl_name)
> >>> +    check ovn-nbctl set ACL $acl_uuid label=$label 
> >>> options:log-related=$log_related
> >>> +}
> >>> +
> >>> +record_log_flows() {
> >>> +    ovn-sbctl lflow-list sw0 | grep -E 'ls_(out|in)_acl.*, 
> >>> priority=65533' | sed 's/table=../table=??/' | sort > log_flows
> >>> +}
> >>> +
> >>> +check_log_flows_count() {
> >>> +    local expected=$1
> >>> +    local table=$2
> >>> +    local count=
> >>> +
> >>> +    echo $table
> >>> +    if test -f log_flows; then
> >>> +        count=$(grep -c -E ls_${table}_acl log_flows)
> >>> +    else
> >>> +        count=$(ovn-sbctl lflow-list sw0 | grep -c -E "ls_$table_acl.*, 
> >>> priority=65533")
> >>> +    fi
> >>> +
> >>> +    check test "$count" -eq "$expected"
> >>> +}
> >>> +
> >>> +ovn_start
> >>> +
> >>> +check ovn-nbctl ls-add sw0
> >>> +check ovn-nbctl lsp-add sw0 sw0-p1 -- lsp-set-addresses sw0-p1 
> >>> "00:00:00:00:00:01 10.0.0.1"
> >>> +check ovn-nbctl lsp-add sw0 sw0-p2 -- lsp-set-addresses sw0-p2 
> >>> "00:00:00:00:00:02 10.0.0.2"
> >>> +
> >>> +check ovn-nbctl pg-add pg1 sw0-p1 sw0-p2
> >>> +check ovn-nbctl pg-add pg2 sw0-p1 sw0-p2
> >>> +check ovn-nbctl pg-add pg3 sw0-p1 sw0-p2
> >>> +
> >>> +check ovn-nbctl --log --name=allow_acl acl-add pg1 from-lport 100 
> >>> 'inport=@pg1 && ip4' allow
> >>> +set_acl_options allow_acl 1 true
> >>> +
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +# An allow ACL should *not* result in a priority 65533 log flow being 
> >>> installed
> >>> +# since there are no stateful ACLs on the system.
> >>> +check_log_flows_count 0 in
> >>> +check_log_flows_count 0 out
> >>> +
> >>> +# Now add an allow-related ACL. This should result in both the 
> >>> allow-related
> >>> +# ACL and the allow ACL having priority 65533 log flows added.
> >>> +check ovn-nbctl --log --name=allow_related_acl acl-add pg2 from-lport 
> >>> 100 'inport=@pg2 && ip4' allow-related
> >>> +set_acl_options allow_related_acl 2 true
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count will be 4 since we have
> >>> +# 2 flows for reply traffic for each ACL
> >>> +# 2 flows for related traffic for each ACL
> >>> +check_log_flows_count 4 out
> >>> +# Since the ACLs are ingress, the ingress table
> >>> +# should have no log flows
> >>> +check_log_flows_count 0 in
> >>> +
> >>> +# Now ensure the flows are what we expect them to be for the ACLs we 
> >>> created
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 2), action=(log(name="allow_related_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 2), action=(log(name="allow_related_acl", 
> >>> severity=info, verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# Now add a stateless-allow ACL.
> >>> +check ovn-nbctl --log --name=allow_stateless_acl acl-add pg3 from-lport 
> >>> 100 'inport=@pg3 && ip4' allow-stateless
> >>> +set_acl_options allow_stateless_acl 3 true
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count will still be 4 since the stateless ACL should not have 
> >>> special log flows created
> >>> +check_log_flows_count 4 out
> >>> +check_log_flows_count 0 in
> >>> +
> >>> +# And the log flows will remain the same since the stateless ACL will 
> >>> not be represented.
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 2), action=(log(name="allow_related_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 2), action=(log(name="allow_related_acl", 
> >>> severity=info, verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# Now remove the label from the allow-related ACL.
> >>> +set_acl_options allow_related_acl 0 true
> >>> +ovn-nbctl --wait=sb sync
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count should now be 2 since the allow_related ACL will not have 
> >>> special
> >>> +# log flows created. But since there there is an allow-related ACL 
> >>> present, the
> >>> +# allow ACL will be stateful and have special log flows created.
> >>> +check_log_flows_count 2 out
> >>> +check_log_flows_count 0 in
> >>> +
> >>> +# And make sure only the allow ACL has the log flows installed
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# And now add the label back, but disable log_related on the 
> >>> allow-related ACL.
> >>> +set_acl_options allow_related_acl 2 false
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count will again be 2 because only the allow ACL will have log 
> >>> flows installed.
> >>> +check_log_flows_count 2 out
> >>> +check_log_flows_count 0 in
> >>> +
> >>> +# And make sure only the allow ACL has the log flows installed
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_out_acl         ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# And just for sanity's sake, let's remove the allow-related ACL and 
> >>> make sure
> >>> +# all the special log messages are gone.
> >>> +check ovn-nbctl acl-del pg2
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +check_log_flows_count 0 out
> >>> +check_log_flows_count 0 in
> >>> +
> >>> +# Now let's clear out all the ACLs, and re-do everything but with egress 
> >>> ACLs.
> >>> +check ovn-nbctl acl-del pg1
> >>> +check ovn-nbctl acl-del pg3
> >>> +check_row_count nb:ACL 0
> >>> +
> >>> +# Start again with an allow_acl only
> >>> +check ovn-nbctl --log --name=allow_acl acl-add pg1 to-lport 100 
> >>> 'inport=@pg1 && ip4' allow
> >>> +set_acl_options allow_acl 1 true
> >>> +
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +# Again, the allow ACL is stateless, so no related log flows.
> >>> +check_log_flows_count 0 in
> >>> +check_log_flows_count 0 out
> >>> +
> >>> +# Adding a new allow-related ACL...
> >>> +check ovn-nbctl --log --name=allow_related_acl acl-add pg2 to-lport 100 
> >>> 'inport=@pg2 && ip4' allow-related
> >>> +set_acl_options allow_related_acl 2 true
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count will be 4 since we have
> >>> +# 2 flows for reply traffic for each ACL
> >>> +# 2 flows for related traffic for each ACL
> >>> +check_log_flows_count 4 in
> >>> +# And this time, we should have no egress flows
> >>> +check_log_flows_count 0 out
> >>> +
> >>> +# Now ensure the flows are what we expect them to be for the ACLs we 
> >>> created
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 2), action=(log(name="allow_related_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 2), action=(log(name="allow_related_acl", 
> >>> severity=info, verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# Now add a stateless-allow ACL.
> >>> +check ovn-nbctl --log --name=allow_stateless_acl acl-add pg3 from-lport 
> >>> 100 'inport=@pg3 && ip4' allow-stateless
> >>> +set_acl_options allow_stateless_acl 3 true
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count will still be 4 since the stateless ACL should not have 
> >>> special log flows created
> >>> +check_log_flows_count 4 in
> >>> +check_log_flows_count 0 out
> >>> +
> >>> +# And the log flows will remain the same since the stateless ACL will 
> >>> not be represented.
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 2), action=(log(name="allow_related_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 2), action=(log(name="allow_related_acl", 
> >>> severity=info, verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# Now remove the label from the allow-related ACL.
> >>> +set_acl_options allow_related_acl 0 true
> >>> +ovn-nbctl --wait=sb sync
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count should now be 2 since the allow_related ACL will not have 
> >>> special
> >>> +# log flows created. But since there there is an allow-related ACL 
> >>> present, the
> >>> +# allow ACL will be stateful and have special log flows created.
> >>> +check_log_flows_count 2 in
> >>> +check_log_flows_count 0 out
> >>> +
> >>> +# And make sure only the allow ACL has the log flows installed
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# And now add the label back, but disable log_related on the 
> >>> allow-related ACL.
> >>> +set_acl_options allow_related_acl 2 false
> >>> +
> >>> +record_log_flows
> >>> +
> >>> +# The count will again be 2 because only the allow ACL will have log 
> >>> flows installed.
> >>> +check_log_flows_count 2 in
> >>> +check_log_flows_count 0 out
> >>> +
> >>> +# And make sure only the allow ACL has the log flows installed
> >>> +AT_CHECK([cat log_flows], [0], [dnl
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(!ct.est && 
> >>> ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0 && ct_label.label 
> >>> == 1), action=(log(name="allow_acl", severity=info, verdict=allow); next;)
> >>> +  table=??(ls_in_acl          ), priority=65533, match=(ct.est && 
> >>> !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0 && 
> >>> ct_label.label == 1), action=(log(name="allow_acl", severity=info, 
> >>> verdict=allow); next;)
> >>> +])
> >>> +
> >>> +rm log_flows
> >>> +
> >>> +# And just for sanity's sake, let's remove the allow-related ACL and 
> >>> make sure
> >>> +# all the special log messages are gone.
> >>> +check ovn-nbctl acl-del pg2
> >>> +check ovn-nbctl --wait=sb sync
> >>> +
> >>> +check_log_flows_count 0 out
> >>> +check_log_flows_count 0 in
> >>> +
> >>> +
> >>> +
> >>>   AT_CLEANUP
> >>>   ])
> >>> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> >>> index 3ae812296..c70fb2a84 100644
> >>> --- a/tests/system-ovn.at
> >>> +++ b/tests/system-ovn.at
> >>> @@ -7002,3 +7002,362 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port 
> >>> patch-.*/d
> >>>
> >>>   AT_CLEANUP
> >>>   ])
> >>> +
> >>> +OVN_FOR_EACH_NORTHD([
> >>> +AT_SETUP([ACL log_related])
> >>> +
> >>> +CHECK_CONNTRACK()
> >>> +ovn_start
> >>> +
> >>> +OVS_TRAFFIC_VSWITCHD_START()
> >>> +ADD_BR([br-int])
> >>> +
> >>> +set_acl_options() {
> >>> +    local acl_name=$1; shift
> >>> +
> >>> +    local acl_uuid=$(fetch_column nb:ACL _uuid name=$acl_name)
> >>> +    check ovn-nbctl set ACL $acl_uuid "$@"
> >>> +}
> >>> +
> >>> +clear_log() {
> >>> +    ovn-appctl -t ovn-controller vlog/close
> >>> +    rm ovn-controller.log
> >>> +    ovn-appctl -t ovn-controller vlog/reopen
> >>> +}
> >>> +
> >>> +test_ping() {
> >>> +    NS_CHECK_EXEC([sw0-p1],  [ping -q -c 1 -i 0.3 -w 2 10.0.0.2 | 
> >>> FORMAT_PING], \
> >>> +[0], [dnl
> >>> +1 packets transmitted, 1 received, 0% packet loss, time 0ms
> >>> +])
> >>> +}
> >>> +
> >>> +check_acl_log_count() {
> >>> +    local expected_count=$1
> >>> +
> >>> +    AT_CHECK_UNQUOTED([grep -c acl_log ovn-controller.log], [0], [dnl
> >>> +$expected_count
> >>> +])
> >>> +}
> >>> +
> >>> +# Set external-ids in br-int needed for ovn-controller
> >>> +ovs-vsctl \
> >>> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
> >>> +        -- set Open_vSwitch . 
> >>> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> >>> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> >>> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> >>> +        -- set bridge br-int fail-mode=secure 
> >>> other-config:disable-in-band=true
> >>> +
> >>> +# Start ovn-controller
> >>> +start_daemon ovn-controller
> >>> +
> >>> +check ovn-nbctl ls-add sw0
> >>> +check ovn-nbctl lsp-add sw0 sw0-p1 -- lsp-set-addresses sw0-p1 
> >>> "00:00:00:00:00:01 10.0.0.1"
> >>> +check ovn-nbctl lsp-add sw0 sw0-p2 -- lsp-set-addresses sw0-p2 
> >>> "00:00:00:00:00:02 10.0.0.2"
> >>> +
> >>> +check ovn-nbctl pg-add pg1 sw0-p1 sw0-p2
> >>> +
> >>> +ADD_NAMESPACES(sw0-p1)
> >>> +ADD_VETH(sw0-p1, sw0-p1, br-int, "10.0.0.1/24", "00:00:00:00:00:01")
> >>> +ADD_NAMESPACES(sw0-p2)
> >>> +ADD_VETH(sw0-p2, sw0-p2, br-int, "10.0.0.2/24", "00:00:00:00:00:02")
> >>> +
> >>> +wait_for_ports_up
> >>> +
> >>> +check ovn-nbctl --log --name=allow_acl acl-add pg1 from-lport 100 
> >>> 'inport == @pg1 && ip4' allow
> >>> +
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +test_ping
> >>> +
> >>> +# The allow ACL should match on the request and reply traffic, resulting 
> >>> in 2 logs.
> >>> +check_acl_log_count 2
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=2 \
> >>> +    --name=allow_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:02 \
> >>> +    --dl_dst=00:00:00:00:00:01 \
> >>> +    --nw_src=10.0.0.2 \
> >>> +    --nw_dst=10.0.0.1 \
> >>> +    --icmp_type=0 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# Now add a higher-priority stateful ACL that matches on the same
> >>> +# parameters. Don't enable reply logging.
> >>> +check ovn-nbctl --log --name=allow_related_acl acl-add pg1 from-lport 
> >>> 200 'inport == @pg1 && ip4' allow-related
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# Since reply logging is not enabled, the allow-related ACL should match 
> >>> on the
> >>> +# request, but the reply will not be logged.
> >>> +check_acl_log_count 1
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# As a control, set a label on the allow-related ACL, but still don't 
> >>> enable
> >>> +# reply traffic logging.
> >>> +set_acl_options allow_related_acl label=1 options:log-related=false
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# This should have the same result as the previous ping
> >>> +check_acl_log_count 1
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# As another control, remove the label but enable reply logging.
> >>> +set_acl_options allow_related_acl label=0 options:log-related=true
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# This should have the same result as the previous ping
> >>> +check_acl_log_count 1
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# This time, add a label and enable reply logging on the allow_related 
> >>> ACL.
> >>> +set_acl_options allow_related_acl label=1 options:log-related=true
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# Now we should have the request and reply logged.
> >>> +check_acl_log_count 2
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=2 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:02 \
> >>> +    --dl_dst=00:00:00:00:00:01 \
> >>> +    --nw_src=10.0.0.2 \
> >>> +    --nw_dst=10.0.0.1 \
> >>> +    --icmp_type=0 \
> >>> +    --icmp_code=0
> >>> +
> >>> +
> >>> +# And now, let's start from scratch but make sure everything works when
> >>> +# using egress ACLs.
> >>> +check ovn-nbctl acl-del pg1
> >>> +check_row_count nb:ACL 0
> >>> +
> >>> +check ovn-nbctl --log --name=allow_acl acl-add pg1 to-lport 100 'outport 
> >>> == @pg1 && ip4' allow
> >>> +
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# The allow ACL should match on the request and reply traffic, resulting 
> >>> in 2 logs.
> >>> +check_acl_log_count 2
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=2 \
> >>> +    --name=allow_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:02 \
> >>> +    --dl_dst=00:00:00:00:00:01 \
> >>> +    --nw_src=10.0.0.2 \
> >>> +    --nw_dst=10.0.0.1 \
> >>> +    --icmp_type=0 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# Now add a higher-priority stateful ACL that matches on the same
> >>> +# parameters. Don't enable reply logging.
> >>> +check ovn-nbctl --log --name=allow_related_acl acl-add pg1 to-lport 200 
> >>> 'outport == @pg1 && ip4' allow-related
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# Since reply logging is not enabled, the allow-related ACL should match 
> >>> on the
> >>> +# request, but the reply will not be logged.
> >>> +check_acl_log_count 1
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# As a control, set a label on the allow-related ACL, but still don't 
> >>> enable
> >>> +# reply traffic logging.
> >>> +set_acl_options allow_related_acl label=1 options:log-related=false
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# This should have the same result as the previous ping
> >>> +check_acl_log_count 1
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# As another control, remove the label but enable reply logging.
> >>> +set_acl_options allow_related_acl label=0 options:log-related=true
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# This should have the same result as the previous ping
> >>> +check_acl_log_count 1
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +# This time, add a label and enable reply logging on the allow_related 
> >>> ACL.
> >>> +set_acl_options allow_related_acl label=1 options:log-related=true
> >>> +check ovn-nbctl --wait=hv sync
> >>> +
> >>> +clear_log
> >>> +test_ping
> >>> +
> >>> +# Now we should have the request and reply logged.
> >>> +check_acl_log_count 2
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=1 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:01 \
> >>> +    --dl_dst=00:00:00:00:00:02 \
> >>> +    --nw_src=10.0.0.1 \
> >>> +    --nw_dst=10.0.0.2 \
> >>> +    --icmp_type=8 \
> >>> +    --icmp_code=0
> >>> +
> >>> +check $PYTHON $srcdir/check_acl_log.py \
> >>> +    --entry-num=2 \
> >>> +    --name=allow_related_acl \
> >>> +    --verdict=allow \
> >>> +    --protocol=icmp \
> >>> +    --dl_src=00:00:00:00:00:02 \
> >>> +    --dl_dst=00:00:00:00:00:01 \
> >>> +    --nw_src=10.0.0.2 \
> >>> +    --nw_dst=10.0.0.1 \
> >>> +    --icmp_type=0 \
> >>> +    --icmp_code=0
> >>> +
> >>> +
> >>> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
> >>> +
> >>> +as ovn-sb
> >>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >>> +
> >>> +as ovn-nb
> >>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >>> +
> >>> +as northd
> >>> +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
> >>> +
> >>> +as
> >>> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> >>> +/connection dropped.*/d"])
> >>> +
> >>> +AT_CLEANUP
> >>> +])
> >>> --
> >>> 2.31.1
> >>>
> >>> _______________________________________________
> >>> dev mailing list
> >>> [email protected]
> >>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >>>
> >>
> >> _______________________________________________
> >> dev mailing list
> >> [email protected]
> >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >>
> >
>
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>

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

Reply via email to