Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
The FDP team is no longer accepting new bugs in Bugzilla. Please report your issues under FDP project in Jira. Thanks.

Bug 2134138

Summary: [RFE] Support for hierarchical ACLs, implement skip ACLs to jump to next hierarchy
Product: Red Hat Enterprise Linux Fast Datapath Reporter: Surya Seetharaman <surya>
Component: ovn23.06Assignee: Mark Michelson <mmichels>
Status: CLOSED ERRATA QA Contact: Ehsan Elahi <eelahi>
Severity: high Docs Contact:
Priority: high    
Version: FDP 22.LCC: astoycos, ctrautma, echaudro, jiji, jishi, mmichels
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: ovn23.06-23.06.0-141.el8fdp Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2024-01-24 11:05:12 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Surya Seetharaman 2022-10-12 15:00:26 UTC
Description of problem:

ANP, ACL1 - 32000 prio
ANP, ACL2 - 31999 prio - jump to NP ACL’s i.e skip all ACL’s in the range of [32000-3000]
ANP, ACL3 - 31995 prio
ANP, ACL4 - 30000 prio
NP, ACL5 - 1001 prio
NP, ACL6 - 1001 prio
NP, ACL7 - 1001 prio
BANP, ACL8 - 900 prio

Implementation Options:
1) Implement ANP & NP as two stages (probably will need to implement BANP as lower priority to NP - keep it same stage) - will need a new pipeline stage in OVN - we need to be sure ANP will be the last of hierarchies as far as policies go :D
2) Implement ANPs in switches and NPs/BANPs in transit switches or a different router/switch? Not sure… 
3) Trick OVS by setting a flag to resubmit to the same table, so if we matched on the skip ACL then we set flag=1 and rest of the flows in that table for that range are applied only if flag=0? - might be a bit more complicated…

This was discussed in the OVN-OpenShift sync meeting today.

From CMS perspective what we want is for a way to implement the "PASS" Admin Network Policy here, so have a way to say if I hit the PASS ACL rule it will just skip the rest of the ACLs under ANP and go straight to NP evaluation.


Version-Release number of selected component (if applicable):


How reproducible:


Steps to Reproduce:
1.
2.
3.

Actual results:


Expected results:


Additional info:

Comment 3 Mark Michelson 2023-03-21 18:00:30 UTC
Patch series posted for review here: https://patchwork.ozlabs.org/project/ovn/list/?series=347327

Comment 4 OVN Bot 2023-05-19 04:09:04 UTC
ovn23.06 fast-datapath-rhel-9 clone created at https://bugzilla.redhat.com/show_bug.cgi?id=2208427

Comment 7 Ehsan Elahi 2023-12-18 19:48:08 UTC
Verified on:
openvswitch-selinux-extra-policy-1.0-34.el9fdp.noarch
openvswitch2.17-2.17.0-125.el9fdp.x86_64
ovn23.06-23.06.1-71.el9fdp.x86_64
ovn23.06-host-23.06.1-71.el9fdp.x86_64
ovn23.06-central-23.06.1-71.el9fdp.x86_64

Comment 8 Ehsan Elahi 2023-12-18 19:49:00 UTC
Also verified on:

openvswitch-selinux-extra-policy-1.0-31.el8fdp.noarch
openvswitch2.17-2.17.0-125.el8fdp.x86_64
ovn23.06-23.06.1-71.el8fdp.x86_64
ovn23.06-host-23.06.1-71.el8fdp.x86_64
ovn23.06-central-23.06.1-71.el8fdp.x86_64

Comment 9 Ehsan Elahi 2023-12-18 19:51:21 UTC
Test script for ACL Tiers

systemctl start ovn-northd
ovn-nbctl set-connection ptcp:6641
ovn-sbctl set-connection ptcp:6642
systemctl start openvswitch
ovs-vsctl set open . external_ids:system-id=hv1
ifconfig ens1f0 192.168.20.1 netmask 255.255.255.0
ovs-vsctl set open . external_ids:ovn-remote=tcp:192.168.20.1:6642
ovs-vsctl set open . external_ids:ovn-encap-type=geneve
ovs-vsctl set open . external_ids:ovn-encap-ip=192.168.20.1
ovs-vsctl set open . external_ids:ovn-monitor-all=true
systemctl start ovn-controller

acl_tier_test() {
	direction=$1
	options=$2
	thing=$3
	ip=$4
	vm=$5
	# First time, the ping should work
	echo "Pass"
	ip netns exec $vm ping $ip -c 3

	# Add an untiered drop ACL. This should cause pings to fail.
	ovn-nbctl --wait=sb $options acl-add $thing $direction 1000 "ip4.dst == $ip" drop
	acl1_uuid=$(ovn-nbctl --bare --columns _uuid find ACL priority=1000)
	## Ping should fail
	echo "Fail"
	ip netns exec $vm ping $ip -c 3

	# Change the tier to 3. Despite there being "holes" in tiers 0, 1, and 2,
	# the ACL should still apply, and pings should fail.
	ovn-nbctl --wait=sb set ACL $acl1_uuid tier=3
	## Ping still should fail
	echo "Fail"
	ip netns exec $vm ping $ip -c 3

	# Add a tier-0 ACL that allows the traffic. The priority is only 4, but
	# since it is a higher tier, the traffic should be allowed.
	ovn-nbctl --wait=sb $options acl-add $thing $direction 4 "ip4.dst == $ip" allow
	# The ping should work now
	echo "Pass"
	ip netns exec $vm ping $ip -c 3

	# Removing the 0-tier ACL should make traffic go back to being dropped.
	ovn-nbctl --wait=sb acl-del $thing $direction 4 "ip4.dst == $ip"
	## Ping should fail
	echo "Fail"
	ip netns exec $vm ping $ip -c 3

	# Removing all ACLs should make traffic go back to passing.
	ovn-nbctl --wait=sb acl-del $thing
	# The ping should work
	echo "Pass"
	ip netns exec $vm ping $ip -c 3
}

ovn-nbctl ls-add ls
ovn-nbctl lsp-add ls vm1
ovn-nbctl lsp-set-addresses vm1 00:00:00:00:00:01
ovn-nbctl lsp-add ls vm2
ovn-nbctl lsp-set-addresses vm2 00:00:00:00:00:02
ip netns add vm1
ovs-vsctl add-port br-int vm1 -- set interface vm1 type=internal
ip link set vm1 netns vm1
ip netns exec vm1 ip link set vm1 address 00:00:00:00:00:01
ip netns exec vm1 ip addr add 172.16.1.1/24 dev vm1
ip netns exec vm1 ip -6 addr add 2000::1/64 dev vm1
ip netns exec vm1 ip link set vm1 up
ovs-vsctl set Interface vm1 external_ids:iface-id=vm1
ip netns add vm2
ovs-vsctl add-port br-int vm2 -- set interface vm2 type=internal
ip link set vm2 netns vm2
ip netns exec vm2 ip link set vm2 address 00:00:00:00:00:02
ip netns exec vm2 ip addr add 172.16.1.2/24 dev vm2
ip netns exec vm2 ip -6 addr add 2000::2/64 dev vm2
ip netns exec vm2 ip link set vm2 up
ip netns exec vm2 ip link set lo up
ovs-vsctl set Interface vm2 external_ids:iface-id=vm2
ovn-nbctl --wait=hv sync

ip netns exec vm1 ping 172.16.1.2 -c 3
ovn-nbctl pg-add pg vm1 vm2

echo "acl_tier_test from-lport ls 172.16.1.2 vm1"
acl_tier_test from-lport "" ls 172.16.1.2 vm1
echo "acl_tier_test from-lport --apply-after-lb ls 172.16.1.2 vm1"
acl_tier_test from-lport "--apply-after-lb" ls 172.16.1.2 vm1
echo "acl_tier_test to-lport ls 172.16.1.2 vm1"
acl_tier_test to-lport "" ls 172.16.1.2 vm1
echo "acl_tier_test from-lport pg 172.16.1.2 vm1"
acl_tier_test from-lport "" pg 172.16.1.2 vm1
echo "acl_tier_test from-lport --apply-after-lb pg 172.16.1.2 vm1"
acl_tier_test from-lport "--apply-after-lb" pg 172.16.1.2 vm1
echo "acl_tier_test to-lport pg 172.16.1.2 vm1"
acl_tier_test to-lport "" pg 172.16.1.2 vm1

Comment 10 Ehsan Elahi 2023-12-18 19:52:16 UTC
Test script for ACL Tiered Logical Flows:


systemctl start ovn-northd
ovn-nbctl set-connection ptcp:6641
ovn-sbctl set-connection ptcp:6642
systemctl start openvswitch
ovs-vsctl set open . external_ids:system-id=hv1
ifconfig ens1f0 192.168.20.1 netmask 255.255.255.0
ovs-vsctl set open . external_ids:ovn-remote=tcp:192.168.20.1:6642
ovs-vsctl set open . external_ids:ovn-encap-type=geneve
ovs-vsctl set open . external_ids:ovn-encap-ip=192.168.20.1
ovs-vsctl set open . external_ids:ovn-monitor-all=true
systemctl start ovn-controller

acl_tiered_flows_test() {
	direction=$1
	options=$2
	thing=$3
	eval_stage=$4
	action_stage=$5
	eval_stage_table=$6

	if test "$direction" = "from-lport" ; then
		pipeline=ingress
	else
		pipeline=egress
	fi

	# Baseline test. Ensure that no ACL evaluation or tier-related flows are
	# installed.
	# No flow should be found
	echo "0"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	# No flow should be found
	echo "0"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500

	# Add an untiered ACL. Ensure that the ACL appears in the eval stage, and
	# that no tier-related flows appear in the action stage.
	ovn-nbctl --wait=sb $options acl-add $thing $direction 1000 "ip4.addr == 80.111.111.112" drop
	acl1_uuid=$(ovn-nbctl --bare --columns _uuid find ACL priority=1000)
	# A flow with priority=2000 should be found
	echo "1"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000 |grep wc -l
	# No flow should be found
	echo "0"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500

	# Explicitly name the tier on the ACL to be tier 0. This should have no
	# effect on the logical flows.
	ovn-nbctl --wait=sb set ACL $acl1_uuid tier=0
	# A flow with priority=2000 should be found
	echo "1"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	# No flow should be found
	echo "0"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500

	# Change the ACL to tier 1. Now we should see the tier as part of the ACL
	# match, and we should see a flow in the action stage to bump the tier
	# to 1 if there was no match on tier 0.
	ovn-nbctl --wait=sb set ACL $acl1_uuid tier=1
	# A flow with priority=2000 should be found
	echo "1"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	# A flow with priority=500 should be found
	echo "1"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500

	# Change the ACL to tier 3. Ensure the tier match on the ACL has been
	# updated, and ensure we see three flows present for incrementing the
	# tier value in the action stage.
	ovn-nbctl --wait=sb set ACL $acl1_uuid tier=3
	# A flow with priority=2000 should be found
	echo "1"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	# Three flows with priority=500 should be found
	echo "3"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500

	# Add an untiered ACL. Ensure that it matches on tier 0, but otherwise,
	# nothing else should have changed in the logical flows.
	ovn-nbctl --wait=sb $options acl-add $thing $direction 1000 "ip4.addr == 83.104.105.116" allow

	# 2 flows with priority=2000 should be found
	echo "2"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	# Three flows with priority=500 should be found
	echo "3"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500

	# Remove the tier 3 ACL. The remaining ACL is untiered, and there are no
	# other tiered ACLs. So we should go back to not checking the tier
	# number in the ACL match, and there should be no tier-related flows
	# in the action stage.
	ovn-nbctl --wait=sb acl-del $thing $direction 1000 "ip4.addr == 80.111.111.112"
	# Single flow with priority=2000 should be found
	echo "1"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	# No flow should be found
	echo "0"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500

	ovn-nbctl --wait=sb acl-del $thing

	# No flow should be found
	echo "0"
	ovn-sbctl lflow-list ls|grep $eval_stage |grep priority=2000
	# No flow should be found
	echo "0"
	ovn-sbctl lflow-list ls|grep $action_stage |grep priority=500
}


ovn-nbctl ls-add ls
ovn-nbctl lsp-add ls vm1
ovn-nbctl lsp-set-addresses vm1 00:00:00:00:00:01
ovn-nbctl lsp-add ls vm2
ovn-nbctl lsp-set-addresses vm2 00:00:00:00:00:02
ip netns add vm1
ovs-vsctl add-port br-int vm1 -- set interface vm1 type=internal
ip link set vm1 netns vm1
ip netns exec vm1 ip link set vm1 address 00:00:00:00:00:01
ip netns exec vm1 ip addr add 172.16.1.1/24 dev vm1
ip netns exec vm1 ip -6 addr add 2000::1/64 dev vm1
ip netns exec vm1 ip link set vm1 up
ovs-vsctl set Interface vm1 external_ids:iface-id=vm1
ip netns add vm2
ovs-vsctl add-port br-int vm2 -- set interface vm2 type=internal
ip link set vm2 netns vm2
ip netns exec vm2 ip link set vm2 address 00:00:00:00:00:02
ip netns exec vm2 ip addr add 172.16.1.2/24 dev vm2
ip netns exec vm2 ip -6 addr add 2000::2/64 dev vm2
ip netns exec vm2 ip link set vm2 up
ip netns exec vm2 ip link set lo up
ovs-vsctl set Interface vm2 external_ids:iface-id=vm2
ovn-nbctl --wait=hv sync

ip netns exec vm1 ping 172.16.1.2 -c 3
ovn-nbctl pg-add pg vm1 vm2

echo "acl_tiered_flows_test from-lport ls ls_in_acl_eval ls_in_acl_action 8"
acl_tiered_flows_test from-lport "" ls ls_in_acl_eval ls_in_acl_action 8
echo "acl_tiered_flows_test from-lport --apply-after-lb ls ls_in_acl_after_lb_eval ls_in_acl_after_lb_action 18"
acl_tiered_flows_test from-lport "--apply-after-lb" ls ls_in_acl_after_lb_eval ls_in_acl_after_lb_action 18
echo "acl_tiered_flows_test to-lport ls ls_out_acl_eval ls_out_acl_action 4"
acl_tiered_flows_test to-lport "" ls ls_out_acl_eval ls_out_acl_action 4
echo "acl_tiered_flows_test from-lport pg ls_in_acl_eval ls_in_acl_action 8"
acl_tiered_flows_test from-lport "" pg ls_in_acl_eval ls_in_acl_action 8
echo "acl_tiered_flows_test from-lport --apply-after-lb pg ls_in_acl_after_lb_eval ls_in_acl_after_lb_action 18"
acl_tiered_flows_test from-lport "--apply-after-lb" pg ls_in_acl_after_lb_eval ls_in_acl_after_lb_action 18
echo "acl_tiered_flows_test to-lport pg ls_out_acl_eval ls_out_acl_action 4"
acl_tiered_flows_test to-lport "" pg ls_out_acl_eval ls_out_acl_action 4

Comment 11 Ehsan Elahi 2023-12-18 19:55:00 UTC
Script to test if tier can be added in the acl-add command and can be used as a criterion to remove an ACL using the acl-del command:

ovn-nbctl acl-add ls from-lport 1000 "ip" drop
ovn-nbctl --column tier list acl
ovn-nbctl --column priority list acl

ovn-nbctl acl-del ls
ovn-nbctl --tier=3 acl-add ls from-lport 1000 "ip" drop
ovn-nbctl --column tier list acl
ovn-nbctl --column priority list acl

ovn-nbctl --tier=3 acl-add ls from-lport 1001 "ip" drop
ovn-nbctl --column tier list acl
ovn-nbctl --column priority list acl

ovn-nbctl --tier=2 acl-add ls from-lport 1002 "ip" drop
ovn-nbctl --column tier list acl
ovn-nbctl --column priority list acl

# Removing the tier 3 acls from ls should result in 1 ACL remaining
ovn-nbctl --tier=3 acl-del ls
# should be 1
ovn-nbctl --column tier list acl |wc -l

# Add two egress ACLs at tier 2.
ovn-nbctl --tier=2 acl-add ls to-lport 1000 "ip" drop
ovn-nbctl --tier=2 acl-add ls to-lport 1001 "ip" drop
# should be 3
ovn-nbctl --column tier list acl|grep tier|wc -l

# This should remove the egress tier 2 ACLs and leave the ingress tier 2 ACL
ovn-nbctl --tier=2 acl-del ls to-lport
# should be 1
ovn-nbctl --column tier list acl|grep tier|wc -l

# Re-add two ingress ACLs at tier 2.
ovn-nbctl --tier=2 acl-add ls from-lport 1000 "ip" drop
ovn-nbctl --tier=2 acl-add ls from-lport 1001 "ip" drop
# should be 3
ovn-nbctl --column tier list acl|grep tier|wc -l

# Attempt to remove all tier 3 ACLs. All three ACLs are tier 2
# so this shouldn't have any effect.
ovn-nbctl --tier=3 acl-del ls
# should be 3
ovn-nbctl --column tier list acl|grep tier|wc -l

# Attempt to remove all ingress tier 3 ACLs. All three ACLs are tier
# 2, so this shouldn't have any effect.
ovn-nbctl --tier=3 acl-del ls from-lport
# should be 3
ovn-nbctl --column tier list acl|grep tier|wc -l

# Attempt to remove the 1000 priority ACL but specify tier 3. Since
# all ACLs are tier 2, this should have no effect.
ovn-nbctl --tier=3 acl-del ls from-lport 1000 "ip"
# should be 3
ovn-nbctl --column tier list acl|grep tier|wc -l

# Specifying the proper tier should result in all ACLs being deleted.
ovn-nbctl --tier=2 acl-del ls
ovn-nbctl --column tier list acl

# Now let's experiment with identical ACLs at different tiers.
ovn-nbctl --tier=1 acl-add ls from-lport 1000 "ip" drop
ovn-nbctl --tier=2 acl-add ls from-lport 1000 "ip" drop
ovn-nbctl --tier=3 acl-add ls from-lport 1000 "ip" drop
ovn-nbctl --column tier list acl|grep tier

# Specifying tier 1 should result in only one ACL being deleted.
ovn-nbctl --tier=1 acl-del ls from-lport 1000 "ip"
ovn-nbctl --column tier list acl|grep tier

# Not specifying a tier should result in all ACLs being deleted.
ovn-nbctl acl-del ls from-lport 1000 "ip"
ovn-nbctl --column tier list acl

Comment 13 errata-xmlrpc 2024-01-24 11:05:12 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (ovn23.06 bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2024:0388