+ 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": {
@@ -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()
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