[ovs-dev] [PATCH ovn] ovn-northd: Fix IP local multicast flooding.

Mark Michelson mmichels at redhat.com
Wed Feb 26 20:54:01 UTC 2020


Acked-by: Mark Michelson <mmichels at redhat.com>

On 2/14/20 5:42 AM, Dumitru Ceara wrote:
> Skip IGMP and MLD entries learned for local multicast groups when
> generating logical flows. We still allow ovn-controller to learn them as
> it might be useful information for administrators to see that hosts
> register for the groups even though they are not expected to send JOIN
> messages for this range.
> 
> Fixes: ddc64665b678 ("OVN: Add ovn-northd IGMP support")
> Reported-by: Lucas Alvares Gomes <lmartins at redhat.com>
> Reported-at: https://bugzilla.redhat.com/1803008
> Signed-off-by: Dumitru Ceara <dceara at redhat.com>
> ---
>   northd/ovn-northd.c |  15 +++++++
>   tests/ovn.at        | 119 +++++++++++++++++++++++++++++++++++++++++-----------
>   2 files changed, 109 insertions(+), 25 deletions(-)
> 
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index 46521b5..6d95ee2 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -6608,6 +6608,15 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
>               &igmp_group->datapath->mcast_info.sw;
>   
>           if (IN6_IS_ADDR_V4MAPPED(&igmp_group->address)) {
> +            /* RFC 4541, section 2.1.2, item 2: Skip groups in the 224.0.0.X
> +             * range.
> +             */
> +            ovs_be32 group_address =
> +                in6_addr_get_mapped_ipv4(&igmp_group->address);
> +            if (ip_is_local_multicast(group_address)) {
> +                continue;
> +            }
> +
>               if (mcast_sw_info->active_v4_flows >= mcast_sw_info->table_size) {
>                   continue;
>               }
> @@ -6615,6 +6624,12 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
>               ds_put_format(&match, "eth.mcast && ip4 && ip4.dst == %s ",
>                             igmp_group->mcgroup.name);
>           } else {
> +            /* RFC 4291, section 2.7.1: Skip groups that correspond to all
> +             * hosts.
> +             */
> +            if (ipv6_is_all_hosts(&igmp_group->address)) {
> +                continue;
> +            }
>               if (mcast_sw_info->active_v6_flows >= mcast_sw_info->table_size) {
>                   continue;
>               }
> diff --git a/tests/ovn.at b/tests/ovn.at
> index ff9a732..d2f1101 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -15434,7 +15434,7 @@ ovn-nbctl set Logical_Switch sw1       \
>       other_config:mcast_snoop="true"
>   
>   # No IGMP query should be generated by sw1 (mcast_querier="false").
> -truncate -s 0 expected
> +> expected
>   OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>   OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>   OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> @@ -15454,14 +15454,14 @@ send_igmp_v3_report hv2-vif1 hv2 000000000002 $(ip_to_hex 10 0 0 2) f9f9 \
>   
>   # Check that the IGMP Group is learned on both hv.
>   OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" -c`
>       test "${total_entries}" = "2"
>   ])
>   
>   # Send traffic and make sure it gets forwarded only on the two ports that
>   # joined.
> -truncate -s 0 expected
> -truncate -s 0 expected_empty
> +> expected
> +> expected_empty
>   send_ip_multicast_pkt hv1-vif2 hv1 \
>       000000000001 01005e000144 \
>       $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e 20 ca70 11 \
> @@ -15486,15 +15486,15 @@ send_igmp_v3_report hv1-vif1 hv1 \
>   
>   # Check IGMP_Group table on both HV.
>   OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" -c`
>       test "${total_entries}" = "1"
>   ])
>   
>   # Send traffic and make sure it gets forwarded only on the port that joined.
>   as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>   as hv2 reset_pcap_file hv2-vif1 hv2/vif1
> -truncate -s 0 expected
> -truncate -s 0 expected_empty
> +> expected
> +> expected_empty
>   send_ip_multicast_pkt hv1-vif2 hv1 \
>       000000000001 01005e000144 \
>       $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e 20 ca70 11 \
> @@ -15514,10 +15514,43 @@ OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>   # Flush IGMP groups.
>   ovn-sbctl ip-multicast-flush sw1
>   OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" -c`
>       test "${total_entries}" = "0"
>   ])
>   
> +# Check that traffic for 224.0.0.X is flooded even if some hosts register for
> +# it.
> +# Inject IGMP Join for 224.0.0.42 on sw1-p11.
> +send_igmp_v3_report hv1-vif1 hv1 \
> +    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
> +    $(ip_to_hex 224 0 0 42) 04 f9d3 \
> +    /dev/null
> +
> +# Check that the IGMP Group is learned.
> +OVS_WAIT_UNTIL([
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "224.0.0.42" -c`
> +    test "${total_entries}" = "1"
> +])
> +
> +# Send traffic and make sure it gets flooded to all ports.
> +as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> +as hv1 reset_pcap_file hv1-vif2 hv1/vif2
> +as hv2 reset_pcap_file hv2-vif1 hv2/vif1
> +as hv2 reset_pcap_file hv2-vif2 hv2/vif2
> +> expected
> +send_ip_multicast_pkt hv1-vif2 hv1 \
> +    000000000001 01005e000144 \
> +    $(ip_to_hex 10 0 0 42) $(ip_to_hex 224 0 0 42) 1e 01 f989 11 \
> +    e518e518000a4b540000
> +store_ip_multicast_pkt \
> +    000000000001 01005e000144 \
> +    $(ip_to_hex 10 0 0 42) $(ip_to_hex 224 0 0 42) 1e 01 f989 11 \
> +    e518e518000a4b540000 expected
> +
> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> +OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
> +
>   # Enable IGMP snooping and querier on sw2 and set query interval to minimum.
>   ovn-nbctl set Logical_Switch sw2 \
>       other_config:mcast_snoop="true" \
> @@ -15527,7 +15560,7 @@ ovn-nbctl set Logical_Switch sw2 \
>       other_config:mcast_ip4_src="20.0.0.254"
>   
>   # Wait for 1 query interval (1 sec) and check that two queries are generated.
> -truncate -s 0 expected
> +> expected
>   store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected
>   store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected
>   
> @@ -15545,7 +15578,7 @@ ovn-nbctl set Logical_Switch sw3       \
>       other_config:mcast_snoop="true"
>   
>   # Send traffic from sw3 and make sure rtr doesn't relay it.
> -truncate -s 0 expected_empty
> +> expected_empty
>   
>   as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>   as hv1 reset_pcap_file hv1-vif2 hv1/vif2
> @@ -15589,15 +15622,15 @@ send_igmp_v3_report hv2-vif3 hv2 \
>   
>   # Check that the IGMP Group is learned by all switches.
>   OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" -c`
>       test "${total_entries}" = "2"
>   ])
>   
>   # Send traffic from sw3 and make sure it is relayed by rtr.
>   # to ports that joined.
> -truncate -s 0 expected_routed_sw1
> -truncate -s 0 expected_routed_sw2
> -truncate -s 0 expected_empty
> +> expected_routed_sw1
> +> expected_routed_sw2
> +> expected_empty
>   
>   as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>   as hv1 reset_pcap_file hv1-vif2 hv1/vif2
> @@ -15638,16 +15671,16 @@ send_igmp_v3_report hv1-vif4 hv1 \
>   
>   # Check that the IGMP Group is learned by all switches.
>   OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" -c`
>       test "${total_entries}" = "3"
>   ])
>   
>   # Send traffic from sw3 and make sure it is relayed by rtr
>   # to ports that joined.
> -truncate -s 0 expected_routed_sw1
> -truncate -s 0 expected_routed_sw2
> -truncate -s 0 expected_switched
> -truncate -s 0 expected_empty
> +> expected_routed_sw1
> +> expected_routed_sw2
> +> expected_switched
> +> expected_empty
>   
>   as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>   as hv1 reset_pcap_file hv1-vif2 hv1/vif2
> @@ -15689,7 +15722,7 @@ ovn-sbctl ip-multicast-flush sw1
>   ovn-sbctl ip-multicast-flush sw2
>   ovn-sbctl ip-multicast-flush sw3
>   OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" -c`
>       test "${total_entries}" = "0"
>   ])
>   
> @@ -15702,10 +15735,10 @@ as hv2 reset_pcap_file hv2-vif2 hv2/vif2
>   as hv2 reset_pcap_file hv2-vif3 hv2/vif3
>   as hv2 reset_pcap_file hv2-vif4 hv2/vif4
>   
> -truncate -s 0 expected_empty
> -truncate -s 0 expected_switched
> -truncate -s 0 expected_routed
> -truncate -s 0 expected_reports
> +> expected_empty
> +> expected_switched
> +> expected_routed
> +> expected_reports
>   
>   # Enable mcast_flood on sw1-p11
>   ovn-nbctl set Logical_Switch_Port sw1-p11 options:mcast_flood='true'
> @@ -15727,7 +15760,7 @@ send_igmp_v3_report hv1-vif2 hv1 \
>   
>   # Check that the IGMP Group is learned.
>   OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" -c`
>       test "${total_entries}" = "1"
>   ])
>   
> @@ -16077,6 +16110,42 @@ OVS_WAIT_UNTIL([
>       test "${total_entries}" = "0"
>   ])
>   
> +# Check that traffic for "all-hosts" is flooded even if some hosts register
> +# for it.
> +# Inject MLD Join for ff02::1 on sw1-p11.
> +send_mld_v2_report hv1-vif1 hv1 \
> +    000000000001 10000000000000000000000000000001 \
> +    ff020000000000000000000000000001 04 5e8a \
> +    /dev/null
> +
> +# Check that the Multicast Group is learned.
> +OVS_WAIT_UNTIL([
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "ff02::1" -c`
> +    test "${total_entries}" = "1"
> +])
> +
> +# Send traffic and make sure it gets flooded to all ports.
> +as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> +as hv1 reset_pcap_file hv1-vif2 hv1/vif2
> +as hv2 reset_pcap_file hv2-vif1 hv2/vif1
> +as hv2 reset_pcap_file hv2-vif2 hv2/vif2
> +> expected
> +send_ip_multicast_pkt hv1-vif2 hv1 \
> +    000000000001 333300000001 \
> +    10000000000000000000000000000042 ff020000000000000000000000000001 \
> +    000e 01 11 \
> +    93407a69000eb90361736461640a
> +store_ip_multicast_pkt \
> +    000000000001 333300000001 \
> +    10000000000000000000000000000042 ff020000000000000000000000000001 \
> +    000e 01 11 \
> +    93407a69000eb90361736461640a \
> +    expected
> +
> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> +OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
> +
>   # Enable multicast snooping and querier on sw2 and set query interval to
>   # minimum.
>   ovn-nbctl set Logical_Switch sw2 \
> 



More information about the dev mailing list