On Thu, Jul 11, 2019 at 10:57 AM Dumitru Ceara <[email protected]> wrote:
>
> New IP Multicast Snooping Options are added to the Northbound DB
> Logical_Switch:other_config column. These allow enabling IGMP snooping and
> querier on the logical switch and get translated by ovn-northd to rows in
> the IP_Multicast Southbound DB table.
>
> ovn-northd monitors for changes done by ovn-controllers in the Southbound DB
> IGMP_Group table. Based on the entries in IGMP_Group ovn-northd creates
> Multicast_Group entries in the Southbound DB, one per IGMP_Group address X,
> containing the list of logical switch ports (aggregated from all controllers)
> that have IGMP_Group entries for that datapath and address X. ovn-northd
> also creates a logical flow that matches on IP multicast traffic destined
> to address X and outputs it on the tunnel key of the corresponding
> Multicast_Group entry.
>
> Signed-off-by: Dumitru Ceara <[email protected]>
> Acked-by: Mark Michelson <[email protected]>
> ---
> ovn/northd/ovn-northd.c | 460
> ++++++++++++++++++++++++++++++++++++++++++++---
> ovn/ovn-nb.xml | 54 ++++++
> tests/ovn.at | 270 ++++++++++++++++++++++++++++
> tests/system-ovn.at | 119 ++++++++++++
> 4 files changed, 871 insertions(+), 32 deletions(-)
>
<snip>
> +
> +static void
> +build_mcast_groups(struct northd_context *ctx,
> + struct hmap *datapaths, struct hmap *ports,
> + struct hmap *mcast_groups,
> + struct hmap *igmp_groups)
> +{
> + struct ovn_port *op;
> +
> + hmap_init(mcast_groups);
> + hmap_init(igmp_groups);
> +
> + HMAP_FOR_EACH (op, key_node, ports) {
> + if (!op->nbsp) {
> + continue;
> + }
> +
> + if (lsp_is_enabled(op->nbsp)) {
> + ovn_multicast_add(mcast_groups, &mc_flood, op);
> + }
> + }
> +
> + const struct sbrec_igmp_group *sb_igmp, *sb_igmp_next;
> +
> + SBREC_IGMP_GROUP_FOR_EACH_SAFE (sb_igmp, sb_igmp_next, ctx->ovnsb_idl) {
> + /* If this is a stale group (e.g., controller had crashed,
> + * purge it).
> + */
> + if (!sb_igmp->chassis || !sb_igmp->datapath) {
> + sbrec_igmp_group_delete(sb_igmp);
> + continue;
> + }
> +
> + struct ovn_datapath *od =
> + ovn_datapath_from_sbrec(datapaths, sb_igmp->datapath);
> + if (!od) {
> + sbrec_igmp_group_delete(sb_igmp);
> + continue;
> + }
> +
> + ovn_igmp_group_add(mcast_groups, igmp_groups, od, ports,
> + sb_igmp->address, sb_igmp->ports,
> sb_igmp->n_ports);
> + }
> +}
Hi Ben, Mark,
While doing some scale testing I realized that walking the rows of the
IGMP_Group table in ovn-northd in the order we get them from the
database might create an issue: ovn_igmp_group_add will create a new
multicast_group for every unique IGMP group address and allocate a
tunnel-id for it. However, because rows are not processed in the order
they were added to the database, it can happen that multicast groups
that didn't actually change will get a different tunnel-id triggering
a change in the associated logical flows.
In order to avoid this I would need to reuse the tunnel-ids of
multicast groups that didn't change between different runs of the
ovn-northd loop. Until now I thought of two different approaches (both
with advantages and disadvantages):
1. Force ovn-northd to walk the IGMP table in a way that ensures that
IGMP groups are processed in the order they were added to the
database:
Add a column to the IGMP_Group table storing a free running counter
value (unique per ovn-controller instance) and add another compound
index [datapath + address + counter]. Every time an ovn-controller
adds an IGMP group it increments its own counter. Then have ovn-northd
walk the IGMP_Group table with SBREC_IGMP_GROUP_FOR_EACH_BYINDEX which
would give us a stable ordering of the entries.
Advantages:
- relatively straightforward to code and maintain
Disadvantages:
- extra column in SB DB
- populating the index in ovn-northd will take N log(N) operations if
i understand correctly the IDL index implementation (N = number of
IGMP_Group entries in the DB)
2. Maintain a cache (hashtable) of allocated multicast group
tunnel-ids between subsequent runs of the ovn-northd loop:
- Once all IGMP_Group entries are processed and their corresponding
Multicast_Group entries are collected we'd need to store a mapping
(per datapath) between IGMP group address and multicast group
tunnel-id.
- Next time ovn-northd walks the IGMP_Group table, before allocating a
new tunnel-id for a multicast group entry it would check the "cache"
from the previous run. If there's already an entry it would reuse the
tunnel-id. If not, it will have to allocate a tunnel-id. Store the
(IGMP group address, tunnel-id) mapping for next run.
Advantages:
- Changes are all local to ovn-northd, no need to store additional
information in the DB.
- Should be faster on average when processing small batches of new
IGMP_Groups from the DB.
Disadvantages:
- We need a multicast_group tunnel-id allocator. I see there's already
similar code (allocate_tnlid) for datapath tunnel-keys but this will
walk the whole range of tunnel-ids until we find one that's not used.
I'm not completely sure about the worst case complexity of this
approach..
- The code to maintain the tunnel-ids across ovn-northd loop
iterations might end up complicated.
What do you guys think? Any alternatives?
Thanks,
Dumitru
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev