Bug 2177197
| Summary: | ACL subnet exclusion is not optimally traslated to ovs flows | ||
|---|---|---|---|
| Product: | Red Hat Enterprise Linux Fast Datapath | Reporter: | Nadia Pinaeva <npinaeva> |
| Component: | ovn23.06 | Assignee: | Ilya Maximets <i.maximets> |
| Status: | CLOSED ERRATA | QA Contact: | Ehsan Elahi <eelahi> |
| Severity: | unspecified | Docs Contact: | |
| Priority: | high | ||
| Version: | RHEL 8.0 | CC: | ctrautma, echaudro, i.maximets, jiji, jishi, mmichels |
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| Whiteboard: | |||
| Fixed In Version: | ovn23.06-23.06.0-beta.118.el8fdp | Doc Type: | If docs needed, set a value |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2024-01-24 11:05:16 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: | |||
I found a fairly simple way to get rid of most of the unnecessary flows and posted a patch here: https://patchwork.ozlabs.org/project/ovn/patch/20230317192509.1513631-1-i.maximets@ovn.org/ Proposed change ends up with 16 flows in the provided example instead
of 79 with current OVN.
$ ./tests/ovstest test-ovn expr-to-flows <<< "ip4.src == 172.168.0.0/16 && ip4.src != {172.168.13.0/24, 172.168.14.128/28}" | sort
ip,nw_src=172.168.0.0/255.255.1.128
ip,nw_src=172.168.0.0/255.255.3.0
ip,nw_src=172.168.0.0/255.255.4.0
ip,nw_src=172.168.0.0/255.255.8.0
ip,nw_src=172.168.0.16/255.255.1.16
ip,nw_src=172.168.0.32/255.255.1.32
ip,nw_src=172.168.0.64/255.255.1.64
ip,nw_src=172.168.128.0/17
ip,nw_src=172.168.16.0/255.255.16.0
ip,nw_src=172.168.2.0/255.255.2.128
ip,nw_src=172.168.2.16/255.255.2.16
ip,nw_src=172.168.2.32/255.255.2.32
ip,nw_src=172.168.2.64/255.255.2.64
ip,nw_src=172.168.3.0/255.255.3.0
ip,nw_src=172.168.32.0/255.255.32.0
ip,nw_src=172.168.64.0/255.255.64.0
Posted v2 including also aggregation of sub-expressions, e.g. aggregation of multiple subnets into larger ones: https://patchwork.ozlabs.org/project/ovn/list/?series=347051 Moving back to ASSIGNED as it requires a bit more work. v3 is posted for review: https://patchwork.ozlabs.org/project/ovn/list/?series=348628 ovn23.06 fast-datapath-rhel-9 clone created at https://bugzilla.redhat.com/show_bug.cgi?id=2203018 Reproduced in:
[root@hp-dl388g10-01 bz_2177197]# rpm -qa | grep -E 'ovn|openvswitch'
openvswitch-selinux-extra-policy-1.0-34.el9fdp.noarch
ovn23.03-23.03.0-4.el9fdp.x86_64
ovn23.03-central-23.03.0-4.el9fdp.x86_64
ovn23.03-host-23.03.0-4.el9fdp.x86_64
openvswitch2.17-2.17.0-125.el9fdp.x86_64
Here is the reproducer:
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
ovn-nbctl lr-add rtr
ovn-nbctl lrp-add rtr rtr-ls 00:00:00:00:01:00 172.16.1.1/24 2000::1/64
ovn-nbctl lrp-add rtr rtr-ls2 00:00:00:00:02:00 172.16.2.1/24 2002::1/64
ovn-nbctl ls-add ls
ovn-nbctl lsp-add ls ls-rtr
ovn-nbctl lsp-set-addresses ls-rtr 00:00:00:00:01:00
ovn-nbctl lsp-set-type ls-rtr router
ovn-nbctl lsp-set-options ls-rtr router-port=rtr-ls
ovn-nbctl lsp-add ls vm1
ovn-nbctl lsp-set-addresses vm1 00:00:00:00:00:01
ovn-nbctl ls-add ls2
ovn-nbctl lsp-add ls2 ls2-rtr
ovn-nbctl lsp-set-addresses ls2-rtr 00:00:00:00:02:00
ovn-nbctl lsp-set-type ls2-rtr router
ovn-nbctl lsp-set-options ls2-rtr router-port=rtr-ls2
ovn-nbctl lsp-add ls2 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.2/24 dev vm1
ip netns exec vm1 ip -6 addr add 2000::2/64 dev vm1
ip netns exec vm1 ip link set vm1 up
ip netns exec vm1 ip route add default via 172.16.1.1
ip netns exec vm1 ip -6 route add default via 2000::1
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.2.2/24 dev vm2
ip netns exec vm2 ip -6 addr add 2002::2/64 dev vm2
ip netns exec vm2 ip link set vm2 up
ip netns exec vm2 ip link set lo up
ip netns exec vm2 ip route add default via 172.16.2.1
ip netns exec vm2 ip -6 route add default via 2002::1
ovs-vsctl set Interface vm2 external_ids:iface-id=vm2
ip netns exec vm1 ping 172.16.2.2 -c 3
ovn-nbctl pg-add pg1 vm1 vm2
ovn-nbctl --wait=hv acl-add ls to-lport 100 "outport == @pg1 && ip4.src == 172.16.0.0/16 && ip4.src != {172.168.1.0/24, 172.168.3.0/28}" drop
ovn-nbctl --wait=hv sync
[root@hp-dl388g10-01 bz_2177197]# ovs-ofctl dump-flows br-int table=44|wc -l
86
<================ 86 number of flows before fix
Verified on:
root@dell-per740-81 bz_2177197]# rpm -qa | grep -E 'ovn|openvswitch'
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
[root@dell-per740-81 bz_2177197]# ovs-ofctl dump-flows br-int table=44|wc -l
12
<================ 12 number of flows on after fix
Also verified on: root@dell-per740-81 bz_2177197]# rpm -qa | grep -E 'ovn|openvswitch' 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 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 |
Description of problem: ACLs with Match like "ip4.src == 172.168.0.0/16 && ip4.src != {172.168.13.0/24}" are translated into positive subnet match. When there is only 1 subnet in the exclusion, it works fine, but if we add a second subnet, it will generate more flows than actually needed (see the following example). "ip4.src == 172.168.0.0/16 && ip4.src != {172.168.13.0/24, 172.168.14.128/28}" will be translated to 72 flows, when the optimal number is 12. in the following note the first 2 octets are omitted 172.168.13.0/24 = 00001101.* 172.168.14.128/28 = 00001110.1000**** Expected 12 flows to be: ******10.***1* ******10.**1* ******10.*1* 172.168.0.0/255.255.1.0 = ******10.0* 172.168.2.0/255.255.2.0 = ******11.* 172.168.0.0/255.255.2.0 = ******00.* 172.168.0.0/255.255.4.0 = *****0**.* 172.168.0.0/255.255.8.0 = ****0***.* 172.168.16.0/255.255.16.0 = ***1****.* 172.168.32.0/255.255.32.0 = **1*****.* 172.168.64.0/255.255.64.0 = *1******.* 172.168.128.0/17= 1*******.* Actually have 72 flows, here is a subset of them 172.168.0.16/255.255.1.16 = *******0.***1**** 172.168.0.32/255.255.1.32 = *******0.**1***** 172.168.0.64/255.255.1.64 = *******0.*1****** 172.168.0.0/255.255.1.128 = *******0.0******* 172.168.2.16/255.255.2.16 = ******1*.***1**** 172.168.2.32/255.255.2.32 = ******1*.**1***** 172.168.2.64/255.255.2.64 = ******1*.*1****** 172.168.2.0/255.255.2.128 = ******1*.0******* 172.168.0.0/255.255.3.0 = ******00.* 172.168.3.0/255.255.3.0 = ******11.* 172.168.0.0/255.255.4.0 = *****0**.* 172.168.0.16/255.255.4.16 = *****0**.***1**** 172.168.0.32/255.255.4.32 = *****0**.**1***** 172.168.0.64/255.255.4.64 = *****0**.*1****** 172.168.0.0/255.255.4.128 = *****0**.0******* 172.168.0.0/255.255.5.0 = *****0*0.* 172.168.1.0/255.255.5.0 = *****0*1.* 172.168.0.0/255.255.6.0 = *****00*.* 172.168.2.0/255.255.6.0 = *****01*.* looks like some of the flows can be deleted, e.g. 172.168.0.0/255.255.4.0 = *****0**.* 172.168.0.16/255.255.4.16 = *****0**.***1**** 172.168.0.32/255.255.4.32 = *****0**.**1***** 172.168.0.64/255.255.4.64 = *****0**.*1****** 172.168.0.0/255.255.4.128 = *****0**.0******* only the first rule may be left Additional info: I used a python lib to compare the subnet exclusion results, e.g. for the provided example ``` from ipaddress import ip_network, collapse_addresses n1 = ip_network('172.168.0.0/16', False) n2 = ip_network('172.168.13.0/24', False) n3 = ip_network('172.168.14.128/28', False) l = [] for i in n1.address_exclude(n2): if n3.subnet_of(i): l.extend(list(i.address_exclude(n3))) else: l.append(i) print(l, len(l)) ``` the subnets will be different from what ovn generates, but the number is the same, and the logic is somewhat similar. This is binary view of what the script generates for a given example. 172.168.128.0/17 = 1*******.* 172.168.64.0/18 = 01******.* 172.168.32.0/19 = 001*****.* 172.168.16.0/20 = 0001****.* 172.168.0.0/21 = 00000***.* 172.168.8.0/22 = 000010**.* 172.168.12.0/24 = 00001100.* 172.168.15.0/24 = 00001111.* 172.168.14.0/25 = 00001110.0* 172.168.14.192/26 = 00001110.11* 172.168.14.160/27 = 00001110.101* 172.168.14.144/28 = 00001110.1001*