[ovs-dev] [PATCH ovn v2] ovn-northd: Add static IP multicast flood configuration

Mark Michelson mmichels at redhat.com
Thu Sep 26 20:53:26 UTC 2019


Looks good to me

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

On 9/24/19 4:02 AM, Dumitru Ceara wrote:
> Add the following new configuration options to the
> Logical_Switch_Port:options column in the OVN Northbound database:
> 
> - mcast_flood: if set to 'true' all incoming IP multicast traffic
>    (except IP multicast reports) entering the switch will also be
>    flooded on the logical switch port.
> - mcast_flood_reports: if set to 'true' all incoming IP multicast
>    entering the switch will also be flooded on the logical switch
>    port. A clone of the packets is also processed by ovn-controller
>    for snooping.
> 
> Add the following new configuration option to the
> Logical_Router_Port:options column in the OVN Northbound database:
> 
> - mcast_flood: if set to 'true' all incoming IP multicast traffic
>    (including IP multicast reports) entering the router will be also
>    flooded on the logical router port.
> 
> Due to the fact that in the router pipeline multicast reports are
> not treated in a special way there's no need for an explicit
> 'mcast_flood_reports' option for router ports.
> 
> Signed-off-by: Dumitru Ceara <dceara at redhat.com>
> 
> ---
> v2: Rebase & fix tag in ovn-nb.xml
> ---
>   lib/mcast-group-index.h |   2 +
>   northd/ovn-northd.8.xml |  30 +++++--
>   northd/ovn-northd.c     | 212 ++++++++++++++++++++++++++++++++++++++++++------
>   ovn-nb.xml              |  33 ++++++++
>   tests/ovn.at            |  81 +++++++++++++++++-
>   5 files changed, 324 insertions(+), 34 deletions(-)
> 
> diff --git a/lib/mcast-group-index.h b/lib/mcast-group-index.h
> index cb49ad7..ba995ba 100644
> --- a/lib/mcast-group-index.h
> +++ b/lib/mcast-group-index.h
> @@ -28,6 +28,8 @@ enum ovn_mcast_tunnel_keys {
>       OVN_MCAST_FLOOD_TUNNEL_KEY = OVN_MIN_MULTICAST,
>       OVN_MCAST_UNKNOWN_TUNNEL_KEY,
>       OVN_MCAST_MROUTER_FLOOD_TUNNEL_KEY,
> +    OVN_MCAST_MROUTER_STATIC_TUNNEL_KEY,
> +    OVN_MCAST_STATIC_TUNNEL_KEY,
>       OVN_MIN_IP_MULTICAST,
>       OVN_MAX_IP_MULTICAST = OVN_MAX_MULTICAST,
>   };
> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> index 0f4f1c1..429ed7e 100644
> --- a/northd/ovn-northd.8.xml
> +++ b/northd/ovn-northd.8.xml
> @@ -954,7 +954,11 @@ output;
>         <li>
>           A priority-100 flow that punts all IGMP packets to
>           <code>ovn-controller</code> if IGMP snooping is enabled on the
> -        logical switch.
> +        logical switch. The flow also forwards the IGMP packets to the
> +        <code>MC_MROUTER_STATIC</code> multicast group, which
> +        <code>ovn-northd</code> populates with all the logical ports that
> +        have <ref column="options" table="Logical_Switch_Port"/>
> +        <code>:mcast_flood_reports='true'</code>.
>         </li>
>   
>         <li>
> @@ -976,10 +980,15 @@ output;
>   
>         <li>
>           A priority-80 flow that forwards all unregistered IP multicast traffic
> -        to the <code>MC_MROUTER_FLOOD</code> multicast group, if any.
> -        Otherwise the flow drops all unregistered IP multicast packets.  This
> -        flow is added only if <ref column="other_config"
> -        table="Logical_Switch"/>:mcast_flood_unregistered='false'.
> +        to the <code>MC_STATIC</code> multicast group, which
> +        <code>ovn-northd</code> populates with all the logical ports that
> +        have <ref column="options" table="Logical_Switch_Port"/>
> +        <code>:mcast_flood='true'</code>. The flow also forwards
> +        unregistered IP multicast traffic to the <code>MC_MROUTER_FLOOD</code>
> +        multicast group, which <code>ovn-northd</code> populates with all the
> +        logical ports connected to logical routers that have
> +        <ref column="options" table="Logical_Router"/>
> +        <code>:mcast_relay='true'</code>.
>         </li>
>   
>         <li>
> @@ -2027,6 +2036,17 @@ output;
>   
>         <li>
>           <p>
> +          Priority-450 flow that matches unregistered IP multicast traffic
> +          and sets <code>outport</code> to the <code>MC_STATIC</code>
> +          multicast group, which <code>ovn-northd</code> populates with the
> +          logical ports that have
> +          <ref column="options" table="Logical_Router_Port"/>
> +          <code>:mcast_flood='true'</code>.
> +        </p>
> +      </li>
> +
> +      <li>
> +        <p>
>             For distributed logical routers where one of the logical router
>             ports specifies a <code>redirect-chassis</code>, a priority-400
>             logical flow for each ip source/destination couple that matches the
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index f393ceb..538daa1 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -448,7 +448,12 @@ struct mcast_switch_info {
>                                    * should be flooded to the mrouter. Only
>                                    * applicable if flood_unregistered == false.
>                                    */
> -
> +    bool flood_reports;         /* True if the switch has at least one port
> +                                 * configured to flood reports.
> +                                 */
> +    bool flood_static;          /* True if the switch has at least one port
> +                                 * configured to flood traffic.
> +                                 */
>       int64_t table_size;         /* Max number of IP multicast groups. */
>       int64_t idle_timeout;       /* Timeout after which an idle group is
>                                    * flushed.
> @@ -466,7 +471,10 @@ struct mcast_switch_info {
>   };
>   
>   struct mcast_router_info {
> -    bool relay; /* True if the router should relay IP multicast. */
> +    bool relay;        /* True if the router should relay IP multicast. */
> +    bool flood_static; /* True if the router has at least one port configured
> +                        * to flood traffic.
> +                        */
>   };
>   
>   struct mcast_info {
> @@ -481,6 +489,34 @@ struct mcast_info {
>       };
>   };
>   
> +struct mcast_port_info {
> +    bool flood;         /* True if the port should flood IP multicast traffic
> +                         * regardless if it's registered or not. */
> +    bool flood_reports; /* True if the port should flood IP multicast reports
> +                         * (e.g., IGMP join/leave). */
> +};
> +
> +static void
> +init_mcast_port_info(struct mcast_port_info *mcast_info,
> +                     const struct nbrec_logical_switch_port *nbsp,
> +                     const struct nbrec_logical_router_port *nbrp)
> +{
> +    if (nbsp) {
> +        mcast_info->flood =
> +            smap_get_bool(&nbsp->options, "mcast_flood", false);
> +        mcast_info->flood_reports =
> +            smap_get_bool(&nbsp->options, "mcast_flood_reports",
> +                          false);
> +    } else if (nbrp) {
> +        /* We don't process multicast reports in any special way on logical
> +         * routers so just treat them as regular multicast traffic.
> +         */
> +        mcast_info->flood =
> +            smap_get_bool(&nbrp->options, "mcast_flood", false);
> +        mcast_info->flood_reports = mcast_info->flood;
> +    }
> +}
> +
>   static uint32_t
>   ovn_mcast_group_allocate_key(struct mcast_info *mcast_info)
>   {
> @@ -1022,7 +1058,7 @@ build_datapaths(struct northd_context *ctx, struct hmap *datapaths,
>           ovn_datapath_destroy(datapaths, od);
>       }
>   }
> -
> +
>   struct ovn_port {
>       struct hmap_node key_node;  /* Index on 'key'. */
>       char *key;                  /* nbs->name, nbr->name, sb->logical_port. */
> @@ -1044,6 +1080,9 @@ struct ovn_port {
>   
>       struct lport_addresses lrp_networks;
>   
> +    /* Logical port multicast data. */
> +    struct mcast_port_info mcast_info;
> +
>       bool derived; /* Indicates whether this is an additional port
>                      * derived from nbsp or nbrp. */
>   
> @@ -1060,6 +1099,23 @@ struct ovn_port {
>       struct ovs_list list;       /* In list of similar records. */
>   };
>   
> +static void
> +ovn_port_set_sb(struct ovn_port *op,
> +                const struct sbrec_port_binding *sb)
> +{
> +    op->sb = sb;
> +}
> +
> +static void
> +ovn_port_set_nb(struct ovn_port *op,
> +                const struct nbrec_logical_switch_port *nbsp,
> +                const struct nbrec_logical_router_port *nbrp)
> +{
> +    op->nbsp = nbsp;
> +    op->nbrp = nbrp;
> +    init_mcast_port_info(&op->mcast_info, op->nbsp, op->nbrp);
> +}
> +
>   static struct ovn_port *
>   ovn_port_create(struct hmap *ports, const char *key,
>                   const struct nbrec_logical_switch_port *nbsp,
> @@ -1073,9 +1129,8 @@ ovn_port_create(struct hmap *ports, const char *key,
>       op->json_key = ds_steal_cstr(&json_key);
>   
>       op->key = xstrdup(key);
> -    op->sb = sb;
> -    op->nbsp = nbsp;
> -    op->nbrp = nbrp;
> +    ovn_port_set_sb(op, sb);
> +    ovn_port_set_nb(op, nbsp, nbrp);
>       op->derived = false;
>       hmap_insert(ports, &op->key_node, hash_string(op->key, 0));
>       return op;
> @@ -1878,7 +1933,7 @@ join_logical_ports(struct northd_context *ctx,
>                                        nbsp->name);
>                           continue;
>                       }
> -                    op->nbsp = nbsp;
> +                    ovn_port_set_nb(op, nbsp, NULL);
>                       ovs_list_remove(&op->list);
>   
>                       uint32_t queue_id = smap_get_int(&op->sb->options,
> @@ -1969,7 +2024,7 @@ join_logical_ports(struct northd_context *ctx,
>                                        nbrp->name);
>                           continue;
>                       }
> -                    op->nbrp = nbrp;
> +                    ovn_port_set_nb(op, NULL, nbrp);
>                       ovs_list_remove(&op->list);
>                       ovs_list_push_back(both, &op->list);
>   
> @@ -2014,7 +2069,7 @@ join_logical_ports(struct northd_context *ctx,
>                       struct ovn_port *crp = ovn_port_find(ports, redirect_name);
>                       if (crp) {
>                           crp->derived = true;
> -                        crp->nbrp = nbrp;
> +                        ovn_port_set_nb(crp, NULL, nbrp);
>                           ovs_list_remove(&crp->list);
>                           ovs_list_push_back(both, &crp->list);
>                       } else {
> @@ -2890,7 +2945,7 @@ build_ports(struct northd_context *ctx,
>               continue;
>           }
>   
> -        op->sb = sbrec_port_binding_insert(ctx->ovnsb_txn);
> +        ovn_port_set_sb(op, sbrec_port_binding_insert(ctx->ovnsb_txn));
>           ovn_port_update_sbrec(ctx, sbrec_chassis_by_name, op,
>                                 &chassis_qdisc_queues,
>                                 &active_ha_chassis_grps);
> @@ -2932,6 +2987,14 @@ static const struct multicast_group mc_flood =
>   static const struct multicast_group mc_mrouter_flood =
>       { MC_MROUTER_FLOOD, OVN_MCAST_MROUTER_FLOOD_TUNNEL_KEY };
>   
> +#define MC_MROUTER_STATIC "_MC_mrouter_static"
> +static const struct multicast_group mc_mrouter_static =
> +    { MC_MROUTER_STATIC, OVN_MCAST_MROUTER_STATIC_TUNNEL_KEY };
> +
> +#define MC_STATIC "_MC_static"
> +static const struct multicast_group mc_static =
> +    { MC_STATIC, OVN_MCAST_STATIC_TUNNEL_KEY };
> +
>   #define MC_UNKNOWN "_MC_unknown"
>   static const struct multicast_group mc_unknown =
>       { MC_UNKNOWN, OVN_MCAST_UNKNOWN_TUNNEL_KEY };
> @@ -3145,7 +3208,23 @@ ovn_igmp_group_get_ports(const struct sbrec_igmp_group *sb_igmp_group,
>   
>        *n_ports = 0;
>        for (size_t i = 0; i < sb_igmp_group->n_ports; i++) {
> -        ports[(*n_ports)] =
> +        struct ovn_port *port =
> +            ovn_port_find(ovn_ports, sb_igmp_group->ports[i]->logical_port);
> +
> +        /* If this is already a flood port skip it for the group. */
> +        if (port->mcast_info.flood) {
> +            continue;
> +        }
> +
> +        /* If this is already a port of a router on which relay is enabled,
> +         * skip it for the group. Traffic is flooded there anyway.
> +         */
> +        if (port->peer && port->peer->od &&
> +                port->peer->od->mcast_info.rtr.relay) {
> +            continue;
> +        }
> +
> +        ports[(*n_ports)] = port;
>               ovn_port_find(ovn_ports, sb_igmp_group->ports[i]->logical_port);
>           if (ports[(*n_ports)]) {
>               (*n_ports)++;
> @@ -5440,9 +5519,18 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
>           struct mcast_switch_info *mcast_sw_info = &od->mcast_info.sw;
>   
>           if (mcast_sw_info->enabled) {
> +            ds_clear(&actions);
> +            if (mcast_sw_info->flood_reports) {
> +                ds_put_cstr(&actions,
> +                            "clone { "
> +                                "outport = \""MC_MROUTER_STATIC"\"; "
> +                                "output; "
> +                            "};");
> +            }
> +            ds_put_cstr(&actions, "igmp;");
>               /* Punt IGMP traffic to controller. */
>               ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 100,
> -                          "ip4 && ip.proto == 2", "igmp;");
> +                          "ip4 && ip.proto == 2", ds_cstr(&actions));
>   
>               /* Flood all IP multicast traffic destined to 224.0.0.X to all
>                * ports - RFC 4541, section 2.1.2, item 2.
> @@ -5451,17 +5539,30 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
>                             "ip4 && ip4.dst == 224.0.0.0/24",
>                             "outport = \""MC_FLOOD"\"; output;");
>   
> -            /* Drop unregistered IP multicast if not allowed. */
> +            /* Forward uregistered IP multicast to routers with relay enabled
> +             * and to any ports configured to flood IP multicast traffic.
> +             * If configured to flood unregistered traffic this will be
> +             * handled by the L2 multicast flow.
> +             */
>               if (!mcast_sw_info->flood_unregistered) {
> -                /* Forward unregistered IP multicast to mrouter (if any). */
> +                ds_clear(&actions);
> +
>                   if (mcast_sw_info->flood_relay) {
> -                    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 80,
> -                                  "ip4 && ip4.mcast",
> -                                  "outport = \""MC_MROUTER_FLOOD"\"; output;");
> +                    ds_put_cstr(&actions,
> +                                "clone { "
> +                                    "outport = \""MC_MROUTER_FLOOD"\"; "
> +                                    "output; "
> +                                "}; ");
> +                }
> +
> +                if (mcast_sw_info->flood_static) {
> +                    ds_put_cstr(&actions, "outport =\""MC_STATIC"\"; output;");
>                   } else {
> -                    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 80,
> -                                  "ip4 && ip4.mcast", "drop;");
> +                    ds_put_cstr(&actions, "drop;");
>                   }
> +
> +                ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 80,
> +                              "ip4 && ip4.mcast", ds_cstr(&actions));
>               }
>           }
>   
> @@ -5491,11 +5592,20 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
>   
>           ds_put_format(&match, "eth.mcast && ip4 && ip4.dst == %s ",
>                         igmp_group->mcgroup.name);
> +
>           /* Also flood traffic to all multicast routers with relay enabled. */
>           if (mcast_sw_info->flood_relay) {
>               ds_put_cstr(&actions,
>                           "clone { "
> -                            "outport = \""MC_MROUTER_FLOOD "\"; output; "
> +                            "outport = \""MC_MROUTER_FLOOD "\"; "
> +                            "output; "
> +                        "};");
> +        }
> +        if (mcast_sw_info->flood_static) {
> +            ds_put_cstr(&actions,
> +                        "clone { "
> +                            "outport =\""MC_STATIC"\"; "
> +                            "output; "
>                           "};");
>           }
>           ds_put_format(&actions, "outport = \"%s\"; output; ",
> @@ -7711,6 +7821,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
>           if (!od->nbr || !od->mcast_info.rtr.relay) {
>               continue;
>           }
> +
>           struct ovn_igmp_group *igmp_group;
>   
>           LIST_FOR_EACH (igmp_group, list_node, &od->mcast_info.groups) {
> @@ -7718,11 +7829,35 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
>               ds_clear(&actions);
>               ds_put_format(&match, "ip4 && ip4.dst == %s ",
>                             igmp_group->mcgroup.name);
> +            if (od->mcast_info.rtr.flood_static) {
> +                ds_put_cstr(&actions,
> +                            "clone { "
> +                                "outport = \""MC_STATIC"\"; "
> +                                "ip.ttl--; "
> +                                "next; "
> +                            "};");
> +            }
>               ds_put_format(&actions, "outport = \"%s\"; ip.ttl--; next;",
>                             igmp_group->mcgroup.name);
>               ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, 500,
>                             ds_cstr(&match), ds_cstr(&actions));
>           }
> +
> +        /* If needed, flood unregistered multicast on statically configured
> +         * ports.
> +         */
> +        if (od->mcast_info.rtr.flood_static) {
> +            ds_clear(&match);
> +            ds_clear(&actions);
> +            ds_put_format(&match, "ip4.mcast");
> +            ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, 450,
> +                          "ip4.mcast",
> +                          "clone { "
> +                                "outport = \""MC_STATIC"\"; "
> +                                "ip.ttl--; "
> +                                "next; "
> +                          "};");
> +        }
>       }
>   
>       /* Logical router ingress table 8: Policy.
> @@ -8893,11 +9028,15 @@ build_mcast_groups(struct northd_context *ctx,
>       hmap_init(igmp_groups);
>   
>       HMAP_FOR_EACH (op, key_node, ports) {
> -        if (!op->nbsp) {
> -            continue;
> -        }
> -
> -        if (lsp_is_enabled(op->nbsp)) {
> +        if (op->nbrp && lrport_is_enabled(op->nbrp)) {
> +            /* If this port is configured to always flood multicast traffic
> +             * add it to the MC_STATIC group.
> +             */
> +            if (op->mcast_info.flood) {
> +                ovn_multicast_add(mcast_groups, &mc_static, op);
> +                op->od->mcast_info.rtr.flood_static = true;
> +            }
> +        } else if (op->nbsp && lsp_is_enabled(op->nbsp)) {
>               ovn_multicast_add(mcast_groups, &mc_flood, op);
>   
>               /* If this port is connected to a multicast router then add it
> @@ -8907,6 +9046,22 @@ build_mcast_groups(struct northd_context *ctx,
>                       op->peer->od && op->peer->od->mcast_info.rtr.relay) {
>                   ovn_multicast_add(mcast_groups, &mc_mrouter_flood, op);
>               }
> +
> +            /* If this port is configured to always flood multicast reports
> +             * add it to the MC_MROUTER_STATIC group.
> +             */
> +            if (op->mcast_info.flood_reports) {
> +                ovn_multicast_add(mcast_groups, &mc_mrouter_static, op);
> +                op->od->mcast_info.sw.flood_reports = true;
> +            }
> +
> +            /* If this port is configured to always flood multicast traffic
> +             * add it to the MC_STATIC group.
> +             */
> +            if (op->mcast_info.flood) {
> +                ovn_multicast_add(mcast_groups, &mc_static, op);
> +                op->od->mcast_info.sw.flood_static = true;
> +            }
>           }
>       }
>   
> @@ -8967,8 +9122,13 @@ build_mcast_groups(struct northd_context *ctx,
>           for (size_t i = 0; i < od->n_router_ports; i++) {
>               struct ovn_port *router_port = od->router_ports[i]->peer;
>   
> +            /* If the router the port connects to doesn't have multicast
> +             * relay enabled or if it was already configured to flood
> +             * multicast traffic then skip it.
> +             */
>               if (!router_port || !router_port->od ||
> -                    !router_port->od->mcast_info.rtr.relay) {
> +                    !router_port->od->mcast_info.rtr.relay ||
> +                    router_port->mcast_info.flood) {
>                   continue;
>               }
>   
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index b41b579..1504f8f 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -671,6 +671,26 @@
>           </column>
>         </group>
>   
> +      <group title="IP Multicast Snooping Options">
> +        <p>
> +          These options apply when the port is part of a logical switch
> +          which has <ref table="Logical_Switch" column="other_config"/>
> +          :mcast_snoop set to <code>true</code>.
> +        </p>
> +
> +        <column name="options" key="mcast_flood"
> +                type='{"type": "boolean"}'>
> +          If set to <code>true</code>, multicast packets (except reports) are
> +          unconditionally forwarded to the specific port.
> +        </column>
> +
> +        <column name="options" key="mcast_flood_reports"
> +                type='{"type": "boolean"}'>
> +          If set to <code>true</code>, multicast reports are unconditionally
> +          forwarded to the specific port.
> +        </column>
> +      </group>
> +
>       </group>
>   
>       <group title="Containers">
> @@ -2005,6 +2025,19 @@
>   
>         </column>
>   
> +      <column name="options" key="mcast_flood"
> +              type='{"type": "boolean"}'>
> +        <p>
> +          If set to <code>true</code>, multicast traffic (including reports)
> +          are unconditionally forwarded to the specific port.
> +        </p>
> +
> +        <p>
> +          This option applies when the port is part of a logical router which
> +          has <ref table="Logical_Router" column="options"/>:mcast_relay set
> +          to <code>true</code>.
> +        </p>
> +      </column>
>       </group>
>   
>       <group title="Attachment">
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 04898dd..f03e701 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -15122,7 +15122,6 @@ OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>   
>   # Flush IGMP groups.
>   ovn-sbctl ip-multicast-flush sw1
> -ovn-nbctl --wait=hv -t 3 sync
>   OVS_WAIT_UNTIL([
>       total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
>       test "${total_entries}" = "0"
> @@ -15174,12 +15173,12 @@ send_ip_multicast_pkt hv2-vif4 hv2 \
>   # Sleep a bit to make sure no traffic is received and then check.
>   sleep 1
>   OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [expected_empty])
>   OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>   OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
> +OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [expected_empty])
>   OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected_empty])
>   OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
> +OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>   OVN_CHECK_PACKETS([hv2/vif4-tx.pcap], [expected_empty])
>   
>   # Enable IGMP relay on rtr
> @@ -15250,6 +15249,82 @@ OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected_empty])
>   OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>   OVN_CHECK_PACKETS([hv2/vif4-tx.pcap], [expected_empty])
>   
> +# Flush IGMP groups.
> +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`
> +    test "${total_entries}" = "0"
> +])
> +
> +as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> +as hv1 reset_pcap_file hv1-vif2 hv1/vif2
> +as hv1 reset_pcap_file hv1-vif3 hv1/vif3
> +as hv1 reset_pcap_file hv1-vif4 hv1/vif4
> +as hv2 reset_pcap_file hv2-vif1 hv2/vif1
> +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
> +
> +# Enable mcast_flood on sw1-p11
> +ovn-nbctl set Logical_Switch_Port sw1-p11 options:mcast_flood='true'
> +
> +# Enable mcast_flood_reports on sw1-p21
> +ovn-nbctl set Logical_Switch_Port sw1-p21 options:mcast_flood_reports='true'
> +# Enable mcast_flood on rtr-sw2
> +ovn-nbctl set Logical_Router_Port rtr-sw2 options:mcast_flood='true'
> +# Enable mcast_flood on sw2-p1
> +ovn-nbctl set Logical_Switch_Port sw2-p1 options:mcast_flood='true'
> +
> +ovn-nbctl --wait=hv sync
> +
> +# Inject IGMP Join for 239.0.1.68 on sw1-p12.
> +send_igmp_v3_report hv1-vif2 hv1 \
> +    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
> +    $(ip_to_hex 239 0 1 68) 04 e9b9 \
> +    expected_reports
> +
> +# Check that the IGMP Group is learned.
> +OVS_WAIT_UNTIL([
> +    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> +    test "${total_entries}" = "1"
> +])
> +
> +# Send traffic from sw1-p21
> +send_ip_multicast_pkt hv2-vif1 hv2 \
> +    000000000001 01005e000144 \
> +    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e 20 ca70 11 \
> +    e518e518000a3b3a0000
> +store_ip_multicast_pkt \
> +    000000000001 01005e000144 \
> +    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e 20 ca70 11 \
> +    e518e518000a3b3a0000 expected_switched
> +store_ip_multicast_pkt \
> +    000000000200 01005e000144 \
> +    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e 1f cb70 11 \
> +    e518e518000a3b3a0000 expected_routed
> +
> +# Sleep a bit to make sure no duplicate traffic is received
> +sleep 1
> +
> +# Check that traffic is switched to sw1-p11 and sw1-p12
> +# Check that IGMP join is flooded on sw1-p21
> +# Check that traffic is routed by rtr to rtr-sw2 and then switched to sw2-p1
> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_switched])
> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_switched])
> +OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_routed])
> +OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [expected_empty])
> +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected_reports])
> +OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
> +OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
> +OVN_CHECK_PACKETS([hv2/vif4-tx.pcap], [expected_empty])
> +
>   OVN_CLEANUP([hv1], [hv2])
>   AT_CLEANUP
>   
> 



More information about the dev mailing list