On 1/28/25 8:22 AM, Ales Musil wrote:
> Add new I-P node that will store all the data for IGMP and
> Multicast groups. This node allows to avoid full recompute of lflow
> node when IGMP or Multicast SB table changes.
>
> The node itself still does full recompute for IGMP and Multicast
> changes however this is a compromise between code complexity and
> the time it takes for all lflow to be created. At the same time
> thi brings the benefit of having the data available when there
> is recompute of the lflow node.
>
> As design choice there is only single lflow_ref for all IGMP
> lflows, that makes them not being thread safe and only main thread
> can generate them during full recompute of lflow node. This shouldn't
> be an issue, because the computation of igmp lflow is pretty simple.
>
> Reported-at: https://issues.redhat.com/browse/FDP-756
> Co-authored-by: Jacob Tanenbaum <[email protected]>
> Signed-off-by: Jacob Tanenbaum <[email protected]>
> Suggested-by: Dumitru Ceara <[email protected]>
> Signed-off-by: Ales Musil <[email protected]>
> ---
Hi Ales, Jacob,
> v3: Rebase on top of latest main.
> Add missing _SAFE in table iterator.
> ---
> northd/en-lflow.c | 52 ++++++++-
> northd/en-lflow.h | 1 +
> northd/en-multicast.c | 220 ++++++++++++++++++++++++++++-----------
> northd/en-multicast.h | 24 ++---
> northd/inc-proc-northd.c | 10 +-
> northd/northd.c | 99 +++++++-----------
> northd/northd.h | 10 +-
> tests/ovn-northd.at | 89 ++++++++++++++++
> 8 files changed, 363 insertions(+), 142 deletions(-)
>
[...]
> @@ -17510,6 +17470,40 @@ build_lswitch_and_lrouter_flows(
> free(svc_check_match);
> }
>
> +/* The IGMP flows have to be built in main thread because there is
> + * single lflow_ref for all of them which isn't thread safe.
> + * This shouldn't affect performance as there is a limited how many
> + * IGMP groups can be created. */
> +void
> +build_igmp_lflows(struct hmap *igmp_groups, const struct hmap *ls_datapaths,
> + struct lflow_table *lflows, struct lflow_ref *lflow_ref)
> +{
> + struct ds actions = DS_EMPTY_INITIALIZER;
> + struct ds match = DS_EMPTY_INITIALIZER;
> +
> + struct ovn_datapath *od;
> + HMAP_FOR_EACH (od, key_node, ls_datapaths) {
> + init_mcast_flow_count(od);
> + build_mcast_flood_lswitch(od, lflows, &actions, lflow_ref);
> + }
> +
> + stopwatch_start(LFLOWS_IGMP_STOPWATCH_NAME, time_msec());
> + struct ovn_igmp_group *igmp_group;
> + HMAP_FOR_EACH (igmp_group, hmap_node, igmp_groups) {
> + if (igmp_group->datapath->nbs) {
> + build_lswitch_ip_mcast_igmp_mld(igmp_group, lflows, &actions,
> + &match, lflow_ref);
This all happens now in a single thread, the main thread. However, the
build_lswitch_ip_mcast_igmp_mld() function still increments the atomic
mcast_sw_info->active_v4_flows variable.
We actually have two small "issues" with this:
1. there's no need for an atomic variable
2. we don't need to keep writing to the counter inside the logical
datapath structure; we can just track counts here, locally. That would
also fix an already existing issue: writing to lflow input node data
that should be read-only.
I'd say, let's follow up on this with a new patch. What do you think?
> + } else {
> + build_igmp_flows_for_lrouter(igmp_group, lflows, &actions,
> + &match, lflow_ref);
> + }
> + }
> + stopwatch_stop(LFLOWS_IGMP_STOPWATCH_NAME, time_msec());
> +
> + ds_destroy(&actions);
> + ds_destroy(&match);
> +}
> +
[...]
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index df646ec68..897818b38 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -14445,3 +14445,92 @@ AT_CHECK([ovn-sbctl lflow-list S1 | grep
> ls_out_acl_action | grep priority=500 |
>
> AT_CLEANUP
> ])
> +
> +OVN_FOR_EACH_NORTHD_NO_HV([
> +AT_SETUP([IGMP incremental processing])
> +
> +check_recompute_counter() {
> + lflow_recomp=$(as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> lflow recompute)
> + AT_CHECK([test x$lflow_recomp = x$1])
> +}
> +ovn_start
> +
> +net_add n1
> +sim_add hv1
> +as hv1
> +
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.11
> +
> +sim_add hv2
> +as hv2
> +
> +check ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.2
> +
> +check ovn-nbctl ls-add sw1
> +check ovn-nbctl ls-add sw2
> +
> +check ovn-nbctl lsp-add sw1 sw1-p11
> +check ovn-nbctl lsp-add sw2 sw2-p21
> +
> +check ovn-nbctl lr-add rtr
> +check ovn-nbctl lrp-add rtr rtr-sw1 00:00:00:00:01:00 10.0.0.254/24
> +check ovn-nbctl lrp-add rtr rtr-sw2 00:00:00:00:02:00 10.0.0.254/24
> +
> +
Nit: one line too many
> +check ovn-nbctl lsp-add sw1 sw1-rtr \
> + -- lsp-set-type sw1-rtr router \
> + -- lsp-set-addresses sw1-rtr 00:00:00:00:01:00 \
> + -- lsp-set-options sw1-rtr router-port=rtr-sw1
> +
> +check ovn-nbctl lsp-add sw2 sw2-rtr \
> + -- lsp-set-type sw2-rtr router \
> + -- lsp-set-addresses sw1-rtr 00:00:00:00:02:00 \
> + -- lsp-set-options sw2-rtr router-port=rtr-sw2
> +
> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> +
> +# Create IGMP_Group 239.0.1.68 with port sw1-p11
> +ovn-sbctl create IGMP_Group address=239.0.1.68 \
Nit: check_uuid
> + datapath=$(fetch_column Datapath_Binding _uuid external_ids:name=sw1) \
> + chassis=$(fetch_column Chassis _uuid name=hv1) \
> + chassis_name=hv1 \
> + ports=$(fetch_column Port_Binding _uuid logical_port=sw1-p11)
> +igmp_uuid=$(fetch_column IGMP_GROUP _uuid address=239.0.1.68)
s/IGMP_GROUP/IGMP_Group
> +
> +check ovn-nbctl --wait=sb sync
> +wait_row_count Igmp_Group 1 address=239.0.1.68
> +wait_row_count Multicast_Group 1 name="239.0.1.68"
> +wait_row_count Multicast_Group 1 name="239.0.1.68" ports='[['$(fetch_column
> Port_Binding _uuid logical_port=sw1-p11)']]'
> +ovn-sbctl list igmp_group
Nit: not needed.
> +check_recompute_counter 0
> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
> +
> +check ovn-nbctl set logical_router rtr \
> + options:mcast_relay="true"
Missing --wait=sb sync here (as discussed offline).
> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> +# Update IGMP_Group 239.0.1.68 to include sw2-p21
> +ovn-sbctl add IGMP_Group $igmp_uuid ports $(fetch_column Port_Binding _uuid
> logical_port=sw2-p21)
Nit: check
> +
> +check ovn-nbctl --wait=sb sync
> +wait_row_count IGMP_Group 1 address=239.0.1.68
> +
> +# Check that new Multicast_Group is created
> +wait_row_count Multicast_Group 2 name=239.0.1.68
> +check_recompute_counter 0
> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
> +
> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> +# Delete IGMP_Group 239.0.1.68
> +ovn-sbctl destroy IGMP_Group $igmp_uuid
Nit: check.
checkpatch also reported some of this on the ovsrobot run.
> +check ovn-nbctl --wait=sb sync
> +check_recompute_counter 0
> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
> +
> +wait_row_count IGMP_Group 0 address=239.0.1.68
> +wait_row_count Multicast_Group 0 name=239.0.1.68
> +
> +OVN_CLEANUP([hv1], [hv2])
> +AT_CLEANUP
> +])
I made the small changes and applied this patch to main.
Regards,
Dumitru
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev