From ecd20c415e96cec7043f4b70ce572db3263ba0db Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Tue, 6 Aug 2024 23:58:18 +0200 Subject: [PATCH] logical-fields: Add missing multicast matches for MLD and IGMP. MLD flows are added to pipelines unconditionally in order to avoid sending such traffic through conntrack. The problem is that these matches turn into matches on ip6.dst that end up as exact matches in datapath flows. This means a separate datapath flow per destination IP address. This may cause significant performance issues in setups where traffic for many different IP addresses is passing through. Since network protocol is stored further in the packet, it is evaluated after checking the IP addresses, and so having a match on ip.proto doesn't save us in this scenario. MLD packets are all supposed to be multicast packets and so they all should have multicast destination ethernet addresses. Add the missing eth.mcast6 match to all such packets. This ensures that non-multicast traffic will quickly fail the OpenFlow lookup on such rules and the bits from higher layers will not be added to the match criteria in datapath flows. IGMP did not check for IP address being multicast for some reason, so it didn't cause issues for IPv4 traffic. But let's fix it as well. Signed-off-by: Ilya Maximets --- lib/logical-fields.c | 7 ++++--- tests/ovn.at | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/logical-fields.c b/lib/logical-fields.c index 134d2674fd..2c9d3c61bf 100644 --- a/lib/logical-fields.c +++ b/lib/logical-fields.c @@ -233,7 +233,7 @@ ovn_init_symtab(struct shash *symtab) expr_symtab_add_field(symtab, "icmp4.code", MFF_ICMPV4_CODE, "icmp4", false); - expr_symtab_add_predicate(symtab, "igmp", "ip4 && ip.proto == 2"); + expr_symtab_add_predicate(symtab, "igmp", "ip4.mcast && ip.proto == 2"); expr_symtab_add_field(symtab, "ip6.src", MFF_IPV6_SRC, "ip6", false); expr_symtab_add_field(symtab, "ip6.dst", MFF_IPV6_DST, "ip6", false); @@ -307,11 +307,12 @@ ovn_init_symtab(struct shash *symtab) * (RFC 2710 and RFC 3810). */ expr_symtab_add_predicate(symtab, "mldv1", - "ip6.src == fe80::/10 && " + "eth.mcastv6 && ip6.src == fe80::/10 && " "icmp6.type == {130, 131, 132}"); /* MLDv2 packets are sent to ff02::16 (RFC 3810, 5.2.14) */ expr_symtab_add_predicate(symtab, "mldv2", - "ip6.dst == ff02::16 && icmp6.type == 143"); + "eth.mcastv6 && ip6.dst == ff02::16 && " + "icmp6.type == 143"); expr_symtab_add_predicate(symtab, "tcp", "ip.proto == 6"); expr_symtab_add_field(symtab, "tcp.src", MFF_TCP_SRC, "tcp", false); diff --git a/tests/ovn.at b/tests/ovn.at index 7ccbbff662..a20e41a8f0 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -5915,8 +5915,8 @@ for i in 1 2 3; do # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD sip=:: - test_icmpv6 ${i}3 f0:00:00:00:0${i}:${i}3 f0:00:00:00:00:21 $sip ff02::16:0 "ICMPv6MLReport()" 21 - test_icmpv6 ${i}3 f0:00:00:00:0${i}:${i}3 f0:00:00:00:00:21 $sip ff02::16:0 "ICMPv6MLReport2()" 21 + test_icmpv6 ${i}3 33:33:00:16:00:00 f0:00:00:00:00:21 $sip ff02::16:0 "ICMPv6MLReport()" 21 + test_icmpv6 ${i}3 33:33:00:16:00:00 f0:00:00:00:00:21 $sip ff02::16:0 "ICMPv6MLReport2()" 21 test_icmpv6 ${i}3 f0:00:00:00:0${i}:${i}3 f0:00:00:00:00:21 $sip ff02::ea:2aea:fffe:2800 "ICMPv6ND_NS()" 21 # Traffic to non-multicast traffic should be dropped test_icmpv6 ${i}3 f0:00:00:00:0${i}:${i}3 f0:00:00:00:00:21 $sip $tip "ICMPv6MLReport()" @@ -14446,8 +14446,8 @@ test_mldv2() { local inport=$1 outport=$2 src_mac=$3 src_ip=$4 packet=$(fmt_pkt " - Ether(dst='ff:ff:ff:ff:ff:ff', src='${src_mac}') / - IPv6(src='${src_ip}', dst='ff02::2') / + Ether(dst='33:33:00:00:00:01', src='${src_mac}') / + IPv6(src='${src_ip}', dst='ff02::1') / ICMPv6MLQuery2() ") as hv1 ovs-appctl netdev-dummy/receive vif${inport} $packet