diff mbox series

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

Message ID 1581676931-1957-1-git-send-email-dceara@redhat.com
State Accepted
Headers show
Series [ovs-dev,ovn] ovn-northd: Fix IP local multicast flooding. | expand

Commit Message

Dumitru Ceara Feb. 14, 2020, 10:42 a.m. UTC
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@redhat.com>
Reported-at: https://bugzilla.redhat.com/1803008
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
---
 northd/ovn-northd.c |  15 +++++++
 tests/ovn.at        | 119 +++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 109 insertions(+), 25 deletions(-)

Comments

Dumitru Ceara Feb. 14, 2020, 10:49 a.m. UTC | #1
On 2/14/20 11: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@redhat.com>
> Reported-at: https://bugzilla.redhat.com/1803008
> Signed-off-by: Dumitru Ceara <dceara@redhat.com>

Please also backport this to branch-20.03.

Thanks,
Dumitru
Mark Michelson Feb. 26, 2020, 8:54 p.m. UTC | #2
Acked-by: Mark Michelson <mmichels@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@redhat.com>
> Reported-at: https://bugzilla.redhat.com/1803008
> Signed-off-by: Dumitru Ceara <dceara@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 \
>
Numan Siddique Feb. 27, 2020, 7:52 a.m. UTC | #3
On Thu, Feb 27, 2020 at 2:24 AM Mark Michelson <mmichels@redhat.com> wrote:
>
> Acked-by: Mark Michelson <mmichels@redhat.com>

Thanks Dumitru and Mark.

I applied this patch to master and branch-20.03

Thanks
Numan

>
> 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@redhat.com>
> > Reported-at: https://bugzilla.redhat.com/1803008
> > Signed-off-by: Dumitru Ceara <dceara@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 \
> >
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Dumitru Ceara Feb. 27, 2020, 8:44 a.m. UTC | #4
On 2/27/20 8:52 AM, Numan Siddique wrote:
> On Thu, Feb 27, 2020 at 2:24 AM Mark Michelson <mmichels@redhat.com> wrote:
>>
>> Acked-by: Mark Michelson <mmichels@redhat.com>
> 
> Thanks Dumitru and Mark.
> 
> I applied this patch to master and branch-20.03
> 
> Thanks
> Numan
> 

Thanks Mark and Numan!
diff mbox series

Patch

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 \