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 <jtane...@redhat.com> > Signed-off-by: Jacob Tanenbaum <jtane...@redhat.com> > Suggested-by: Dumitru Ceara <dce...@redhat.com> > Signed-off-by: Ales Musil <amu...@redhat.com> > ---
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 d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev