On 9/8/20 2:07 PM, Han Zhou wrote:


On Tue, Sep 8, 2020 at 8:55 AM Mark Michelson <[email protected] <mailto:[email protected]>> wrote:
 >
 > On 9/7/20 2:45 AM, Han Zhou wrote:
 > > This patch optimizes the previous patch that incrementally processes
 > > flow installation by merging the "add-after-delete" flow changes as
 > > much as possible to avoid unnecessary OpenFlow updates.
 > >
 > > Signed-off-by: Han Zhou <[email protected] <mailto:[email protected]>>
 > > ---
> >   controller/ofctrl.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 > >   1 file changed, 74 insertions(+)
 > >
 > > diff --git a/controller/ofctrl.c b/controller/ofctrl.c
 > > index a2aa45d..81a00c8 100644
 > > --- a/controller/ofctrl.c
 > > +++ b/controller/ofctrl.c
> > @@ -1692,10 +1692,84 @@ update_installed_flows_by_compare(struct ovn_desired_flow_table *flow_table,
 > >       }
 > >   }
 > >
> > +/* Finds and returns a desired_flow in 'deleted_flows' that is exactly the
 > > + * same as 'target', including cookie and actions.
 > > + */
 > > +static struct desired_flow *
> > +deleted_flow_lookup(struct hmap *deleted_flows, struct ovn_flow *target)
 > > +{
 > > +    struct desired_flow *d;
 > > +    HMAP_FOR_EACH_WITH_HASH (d, match_hmap_node, target->hash,
 > > +                             deleted_flows) {
 > > +        struct ovn_flow *f = &d->flow;
 > > +        if (f->table_id == target->table_id
 > > +            && f->priority == target->priority
 > > +            && minimatch_equal(&f->match, &target->match)
 > > +            && f->cookie == target->cookie
> > +            && ofpacts_equal(f->ofpacts, f->ofpacts_len, target->ofpacts,
 > > +                             target->ofpacts_len)) {
 > > +            return d;
 > > +        }
 > > +    }
 > > +    return NULL;
 > > +}
 > > +
> > +/* This function scans the tracked flow changes in the order and merges "add" > > + * or "update" after "deleted" operations for exactly same flow (priority, > > + * table, match, action and cookie), to avoid unnecessary OF messages being
 > > + * sent to OVS. */
 > > +static void
 > > +merge_tracked_flows(struct ovn_desired_flow_table *flow_table)
 > > +{
 > > +    struct hmap deleted_flows = HMAP_INITIALIZER(&deleted_flows);
 > > +    struct desired_flow *f, *next;
 > > +    LIST_FOR_EACH_SAFE (f, next, track_list_node,
 > > +                        &flow_table->tracked_flows) {
 > > +        if (f->is_deleted) {
> > +            /* reuse f->match_hmap_node field since it is already removed from
 > > +             * the desired flow table's match index. */
 > > +            hmap_insert(&deleted_flows, &f->match_hmap_node,
 > > +                        f->flow.hash);
 > > +        } else {
> > +            struct desired_flow *del_f = deleted_flow_lookup(&deleted_flows, > > + &f->flow);
 > > +            if (!del_f) {
 > > +                continue;
 > > +            }
 > > +
> > +            /* del_f must have been installed, otherwise it should have been
 > > +             * removed during track_flow_add_or_modify. */
 > > +            ovs_assert(del_f->installed_flow);
 > > +            if (!f->installed_flow) {
 > > +                /* f is not installed yet. */
 > > +                struct installed_flow *i = del_f->installed_flow;
 > > +                unlink_installed_to_desired(i, del_f);
 > > +                link_installed_to_desired(i, f);
 > > +            } else {
> > +                /* f has been installed before, and now was updated to exact
 > > +                 * the same flow as del_f. */
> > +                ovs_assert(f->installed_flow == del_f->installed_flow); > > +                unlink_installed_to_desired(del_f->installed_flow, del_f);
 > > +            }
 > > +            hmap_remove(&deleted_flows, &del_f->match_hmap_node);
 > > +            ovs_list_remove(&del_f->track_list_node);
 > > +            desired_flow_destroy(del_f);
 > > +
 > > +            ovs_list_remove(&f->track_list_node);
 > > +            ovs_list_init(&f->track_list_node);
 > > +        }
 > > +    }
 >
 > What happens here if the deleted flow comes later in the list than the
 > added/modified flows? Can that happen? If so, then this needs to be
 > separated into two separate list traversals. The first adds all
 > f->is_deleted flows to deleted_flows, and the second modifies the links
 > on all !f->is_deleted flows that are found in deleted_flows.
 >
Hi Mark, "delete-after-add/modify" is handled on-the-fly when the flows add/modify & delete are tracked, in track_flow_del(). Here the function merge_tracked_flows() is to handle the "add-after-delete" only. The "add-after-delete" is handled separately here because a deleted flow is removed from the desired flow table already and the following add operation is operating on a new desired_flow instance instead of the deleted one. Maybe I should add this in comments.


Got it. So the list's order is important here. So if the delete comes before the add/modify, that indicates the overall intention is to really just modify, whereas add/modify before delete means the overall intention is to just delete.

 > > +    HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, &deleted_flows) {
 > > +        hmap_remove(&deleted_flows, &f->match_hmap_node);
 > > +    }
 > > +    hmap_destroy(&deleted_flows);
 > > +}
 > > +
 > >   static void
> >   update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
 > >                                   struct ovs_list *msgs)
 > >   {
 > > +    merge_tracked_flows(flow_table);
 > >       struct desired_flow *f, *f_next;
 > >       LIST_FOR_EACH_SAFE (f, f_next, track_list_node,
 > >                           &flow_table->tracked_flows) {
 > >
 >

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to