diff mbox series

[ovs-dev] ofctrl.c: Avoid repeatedly linking an installed flow and a desired flow.

Message ID 20201002200504.2954064-1-hzhou@ovn.org
State Superseded
Headers show
Series [ovs-dev] ofctrl.c: Avoid repeatedly linking an installed flow and a desired flow. | expand

Commit Message

Han Zhou Oct. 2, 2020, 8:05 p.m. UTC
In update_installed_flows_by_compare() there are two loops. The first
loop iterates the installed flows and find its peer in desired flows to
1. uninstall flows that are not needed anymore
2. update flows if needed
At the same time, it links the desired flow found for the installed flow
which also set the desired flow as the current active installed flow.

The second loop iterates the desired flows and find its peer in installed
flows to install missing flows. At the same time it will detect if there
are conflict desired flows matching same installed flow then just link
them.

However, currently in the second loop, it blindly link the desired flows
to the installed flows, without checking if it is already linked. Lucky
enough, this won't cause any real problem so far, because when there are
conflict flows, the one found in the first loop will also be the one
traversed first in the second loop. After the first loop, each installed
flow will be linked to one and only one desired flow, and in the second
loop the same ones will be readded to the list - readding the only element
in the list becomes a no-op.

However, this is still a bug and this patch fixes it to avoid potential
problems and confusion in the code.

Signed-off-by: Han Zhou <hzhou@ovn.org>
---
 controller/ofctrl.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Dumitru Ceara Oct. 8, 2020, 3:46 p.m. UTC | #1
On 10/2/20 10:05 PM, Han Zhou wrote:
> In update_installed_flows_by_compare() there are two loops. The first
> loop iterates the installed flows and find its peer in desired flows to
> 1. uninstall flows that are not needed anymore
> 2. update flows if needed
> At the same time, it links the desired flow found for the installed flow
> which also set the desired flow as the current active installed flow.
> 
> The second loop iterates the desired flows and find its peer in installed
> flows to install missing flows. At the same time it will detect if there
> are conflict desired flows matching same installed flow then just link
> them.
> 
> However, currently in the second loop, it blindly link the desired flows
> to the installed flows, without checking if it is already linked. Lucky
> enough, this won't cause any real problem so far, because when there are
> conflict flows, the one found in the first loop will also be the one
> traversed first in the second loop. After the first loop, each installed
> flow will be linked to one and only one desired flow, and in the second
> loop the same ones will be readded to the list - readding the only element
> in the list becomes a no-op.
> 
> However, this is still a bug and this patch fixes it to avoid potential
> problems and confusion in the code.
> 
> Signed-off-by: Han Zhou <hzhou@ovn.org>
> ---
>  controller/ofctrl.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/controller/ofctrl.c b/controller/ofctrl.c
> index 81a00c844..3276b45b0 100644
> --- a/controller/ofctrl.c
> +++ b/controller/ofctrl.c
> @@ -1687,8 +1687,12 @@ update_installed_flows_by_compare(struct ovn_desired_flow_table *flow_table,
>              /* Copy 'd' from 'flow_table' to installed_flows. */
>              i = installed_flow_dup(d);
>              hmap_insert(&installed_flows, &i->match_hmap_node, i->flow.hash);
> +            link_installed_to_desired(i, d);
> +        } else if (i->desired_flow != d) {
> +            /* This is a desired_flow that conflicts with one installed
> +             * previously. */
> +            link_installed_to_desired(i, d);
>          }
> -        link_installed_to_desired(i, d);

Hi Han,

Maybe I'm missing something but link_installed_to_desired(i, d) already
returns early if i->desired_flow == d.  It seems to me that the
unpatched version of the code was doing the same thing as it does with
your patch applied.

Regards,
Dumitru

>      }>  }
>  
>
Han Zhou Oct. 8, 2020, 7:43 p.m. UTC | #2
On Thu, Oct 8, 2020 at 8:47 AM Dumitru Ceara <dceara@redhat.com> wrote:
>
> On 10/2/20 10:05 PM, Han Zhou wrote:
> > In update_installed_flows_by_compare() there are two loops. The first
> > loop iterates the installed flows and find its peer in desired flows to
> > 1. uninstall flows that are not needed anymore
> > 2. update flows if needed
> > At the same time, it links the desired flow found for the installed flow
> > which also set the desired flow as the current active installed flow.
> >
> > The second loop iterates the desired flows and find its peer in
installed
> > flows to install missing flows. At the same time it will detect if there
> > are conflict desired flows matching same installed flow then just link
> > them.
> >
> > However, currently in the second loop, it blindly link the desired flows
> > to the installed flows, without checking if it is already linked. Lucky
> > enough, this won't cause any real problem so far, because when there are
> > conflict flows, the one found in the first loop will also be the one
> > traversed first in the second loop. After the first loop, each installed
> > flow will be linked to one and only one desired flow, and in the second
> > loop the same ones will be readded to the list - readding the only
element
> > in the list becomes a no-op.
> >
> > However, this is still a bug and this patch fixes it to avoid potential
> > problems and confusion in the code.
> >
> > Signed-off-by: Han Zhou <hzhou@ovn.org>
> > ---
> >  controller/ofctrl.c | 6 +++++-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> >
> > diff --git a/controller/ofctrl.c b/controller/ofctrl.c
> > index 81a00c844..3276b45b0 100644
> > --- a/controller/ofctrl.c
> > +++ b/controller/ofctrl.c
> > @@ -1687,8 +1687,12 @@ update_installed_flows_by_compare(struct
ovn_desired_flow_table *flow_table,
> >              /* Copy 'd' from 'flow_table' to installed_flows. */
> >              i = installed_flow_dup(d);
> >              hmap_insert(&installed_flows, &i->match_hmap_node,
i->flow.hash);
> > +            link_installed_to_desired(i, d);
> > +        } else if (i->desired_flow != d) {
> > +            /* This is a desired_flow that conflicts with one installed
> > +             * previously. */
> > +            link_installed_to_desired(i, d);
> >          }
> > -        link_installed_to_desired(i, d);
>
> Hi Han,
>
> Maybe I'm missing something but link_installed_to_desired(i, d) already
> returns early if i->desired_flow == d.  It seems to me that the
> unpatched version of the code was doing the same thing as it does with
> your patch applied.
>

Thanks Dumitru. You are right. It was still confusing. I reworked it with
v2. Please take a look:
https://patchwork.ozlabs.org/project/ovn/patch/20201008193402.3786783-1-hzhou@ovn.org/
diff mbox series

Patch

diff --git a/controller/ofctrl.c b/controller/ofctrl.c
index 81a00c844..3276b45b0 100644
--- a/controller/ofctrl.c
+++ b/controller/ofctrl.c
@@ -1687,8 +1687,12 @@  update_installed_flows_by_compare(struct ovn_desired_flow_table *flow_table,
             /* Copy 'd' from 'flow_table' to installed_flows. */
             i = installed_flow_dup(d);
             hmap_insert(&installed_flows, &i->match_hmap_node, i->flow.hash);
+            link_installed_to_desired(i, d);
+        } else if (i->desired_flow != d) {
+            /* This is a desired_flow that conflicts with one installed
+             * previously. */
+            link_installed_to_desired(i, d);
         }
-        link_installed_to_desired(i, d);
     }
 }