Flavio Leitner <f...@sysclose.org> writes:

> Hi Aaron,
>
> Thanks for the patch, see my comments below.
>
> On Fri, Aug 07, 2020 at 05:32:03PM -0400, Aaron Conole wrote:
>> When commit a0baa7dfa4fe ("connmgr: Make treatment of active and passive
>> connections more uniform") was applied, it did not take into account
>> that a reconfiguration of the allowed_versions setting would require a
>> reload of the ofservice object (only accomplished via a restart of OvS).
>> 
>> For now, during the reconfigure cycle, we delete the ofservice object and
>> then recreate it immediately.  A new test is added to ensure we do not
>> break this behavior again.
>> 
>> Fixes: a0baa7dfa4fe ("connmgr: Make treatment of active and passive 
>> connections more uniform")
>> Suggested-by: Ben Pfaff <b...@ovn.org>
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1782834
>> Signed-off-by: Aaron Conole <acon...@redhat.com>
>> ---
>> NOTE: The log on line 608 will flag the 0-day robot, but I thought
>>       for string searching purposes it's better to keep it all one
>>       line.
>> 
>>  ofproto/connmgr.c | 25 +++++++++++++++++++------
>>  tests/bridge.at   | 17 +++++++++++++++++
>>  2 files changed, 36 insertions(+), 6 deletions(-)
>> 
>> diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
>> index 51d656cba9..b57a381097 100644
>> --- a/ofproto/connmgr.c
>> +++ b/ofproto/connmgr.c
>> @@ -190,8 +190,9 @@ struct ofservice {
>>  
>>  static void ofservice_run(struct ofservice *);
>>  static void ofservice_wait(struct ofservice *);
>> -static void ofservice_reconfigure(struct ofservice *,
>> -                                  const struct ofproto_controller *)
>> +static bool ofservice_reconfigure(struct ofservice *,
>> +                                  const struct ofproto_controller *,
>> +                                  bool)
>>      OVS_REQUIRES(ofproto_mutex);
>>  static void ofservice_create(struct connmgr *mgr, const char *target,
>>                               const struct ofproto_controller *)
>> @@ -602,7 +603,14 @@ connmgr_set_controllers(struct connmgr *mgr, struct 
>> shash *controllers)
>>                        target);
>>              ofservice_destroy(ofservice);
>>          } else {
>> -            ofservice_reconfigure(ofservice, c);
>> +            if (ofservice_reconfigure(ofservice, c, true) == false) {
>> +                char *target_to_restore = xstrdup(target);
>> +                VLOG_INFO("%s: restarting controller \"%s\" due to version 
>> change",
>> +                          mgr->name, target);
>> +                ofservice_destroy(ofservice);
>> +                ofservice_create(mgr, target_to_restore, c);
>> +                free(target_to_restore);
>
> This seems more complicated than it needs to be because the only
> situation where we care to re-create is when we set the controller
> and the protocol version has changed, so changing the API of
> reconfigure makes little sense and becomes confusing to follow up.
> E.g. ofservice_reconfigure(.., true) == false.

I thought maybe there could be some other kind of reconfigure situation
in the future that might require a rebuild of the service anyway.  This
is why I wrote the API to return a boolean.  Maybe it would have been
clearer if I set it up as two commits?

> Also that ofservice_create() calls ofservice_reconfigure() again.
> What do you think of this instead?
>
>          /* Changing version requires to re-create ofservice. */
>          if (ofservice->s.allowed_versions == c->allowed_versions) {
>              ofservice_reconfigure(ofservice, c);

If we do this, then we should remove the version check in
the ofservice_reconfigure function also, I think - it would not make
sense any more.

No strong opinion on the approach, though.

>          } else {
>              char *target_to_restore = xstrdup(target);
>              VLOG_INFO("%s: restarting controller \"%s\" due to version 
> change",
>                        mgr->name, target);
>              ofservice_destroy(ofservice);
>              ofservice_create(mgr, target_to_restore, c);
>              free(target_to_restore);
>          }
>
>> +            }
>>          }
>>      }
>>  
>> @@ -1935,7 +1943,7 @@ ofservice_create(struct connmgr *mgr, const char 
>> *target,
>>      ofservice->rconn = rconn;
>>      ofservice->pvconn = pvconn;
>>      ofservice->s = *c;
>> -    ofservice_reconfigure(ofservice, c);
>> +    (void)ofservice_reconfigure(ofservice, c, false);
>
> OVS doesn't use that construct as far as I can tell.

Yes - I wanted to forcibly ignore the return.  I think it isn't needed.

>>  
>>      VLOG_INFO("%s: added %s controller \"%s\"",
>>                mgr->name, ofconn_type_to_string(ofservice->type), target);
>> @@ -2011,9 +2019,10 @@ ofservice_wait(struct ofservice *ofservice)
>>      }
>>  }
>>  
>> -static void
>> +static bool
>>  ofservice_reconfigure(struct ofservice *ofservice,
>> -                      const struct ofproto_controller *settings)
>> +                      const struct ofproto_controller *settings,
>> +                      bool reject_version)
>
> It would be nice to have a documentation about the purpose of
> reject_version.

Maybe a different name, actually?  maybe invert it and call it
'allow_version_mismatch'?  The condition then becomes:

   if (!allow_version_mismatch) {
       return false;
   }

And I would change the calls?

WDYT?

>>      OVS_REQUIRES(ofproto_mutex)
>>  {
>>      /* If the allowed OpenFlow versions change, close all of the existing
>> @@ -2021,6 +2030,9 @@ ofservice_reconfigure(struct ofservice *ofservice,
>>       * version. */
>>      if (ofservice->s.allowed_versions != settings->allowed_versions) {
>>          ofservice_close_all(ofservice);
>> +        if (reject_version) {
>> +            return false;
>> +        }
>>      }
>>  
>>      ofservice->s = *settings;
>> @@ -2029,6 +2041,7 @@ ofservice_reconfigure(struct ofservice *ofservice,
>>      LIST_FOR_EACH (ofconn, ofservice_node, &ofservice->conns) {
>>          ofconn_reconfigure(ofconn, settings);
>>      }
>> +    return true;
>
> The file has mixed styles with and without empty line above
> return. I personally prefer with it to make a clear separation
> but yeah, no strong opinion here.
>
>>  }
>>  
>>  /* Finds and returns the ofservice within 'mgr' that has the given
>> diff --git a/tests/bridge.at b/tests/bridge.at
>> index d48463e263..904f1381c7 100644
>> --- a/tests/bridge.at
>> +++ b/tests/bridge.at
>> @@ -103,3 +103,20 @@ AT_CHECK([ovs-appctl -t ovs-vswitchd version], [0], 
>> [ignore])
>>  OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>  OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>  AT_CLEANUP
>> +
>> +AT_SETUP([bridge - change ofproto versions])
>> +dnl Start vswitch and add a version test bridge
>> +OVS_VSWITCHD_START(
>> +    [add-br vr_test0 -- \
>> +     set bridge vr_test0 datapath-type=dummy \
>> +                         protocols=OpenFlow10])
>> +
>> +dnl set the version to include, say, OpenFlow14
>> +AT_CHECK([ovs-vsctl set bridge vr_test0 protocols=OpenFlow10,OpenFlow14])
>> +
>> +dnl now try to use bundle action on a flow
>> +AT_CHECK([ovs-ofctl add-flow vr_test0 --bundle actions=normal])
>> +
>> +OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>> +AT_CLEANUP
>> -- 
>
> Nice, thanks for adding the test.

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to