diff mbox series

[ovs-dev] ovsdb-idl: Add ovsdb_idl_monitor_condition_pending().

Message ID 1604920181-23904-1-git-send-email-dceara@redhat.com
State Rejected
Headers show
Series [ovs-dev] ovsdb-idl: Add ovsdb_idl_monitor_condition_pending(). | expand

Commit Message

Dumitru Ceara Nov. 9, 2020, 11:09 a.m. UTC
IDL clients had no way of checking whether monitor_cond_change requests
were pending (either local or in flight).  This commit introduces a new
API to check for the state of the conditional monitoring clauses.

Signed-off-by: Dumitru Ceara <dceara@redhat.com>
---
 lib/ovsdb-idl.c | 40 ++++++++++++++++++++++++++++++++--------
 lib/ovsdb-idl.h |  1 +
 2 files changed, 33 insertions(+), 8 deletions(-)

Comments

Ilya Maximets Nov. 10, 2020, 10:07 a.m. UTC | #1
On 11/9/20 12:09 PM, Dumitru Ceara wrote:
> IDL clients had no way of checking whether monitor_cond_change requests
> were pending (either local or in flight).  This commit introduces a new
> API to check for the state of the conditional monitoring clauses.
> 
> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
> ---
>  lib/ovsdb-idl.c | 40 ++++++++++++++++++++++++++++++++--------
>  lib/ovsdb-idl.h |  1 +
>  2 files changed, 33 insertions(+), 8 deletions(-)
> 

<snip>

> diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
> index a1a5776..3f19d40 100644
> --- a/lib/ovsdb-idl.h
> +++ b/lib/ovsdb-idl.h
> @@ -421,6 +421,7 @@ unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *,
>                                       const struct ovsdb_idl_condition *);
>  
>  unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *);
> +bool ovsdb_idl_monitor_condition_pending(struct ovsdb_idl *);

I don't think that we need a new api for this.  Condition sequence number,
I believe, exists for exactly this case.  There is an issue, however, that
db bindings doesn't return result of ovsdb_idl_set_condition() throwing it
away without giving a chance for an idl user to actually use it.  That could
be fixed by something like this:

diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index 698fe25f3..d319adb03 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -1416,10 +1416,10 @@ struct %(s)s *
         print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
             structName, structName.upper()))
         print("""
-void
+unsigned int
 %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition)
 {
-    ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
+    return ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
 }""" % {'p': prefix,
         's': structName,
         'tl': tableName.lower()})
---

I think, I had this patch somewhere already, but it seems that I never
actually send it.

With this change ovn-controller will need to store the returned value
and wait until current condition seqno != expected to be sure that
condition was successfully set.

What do you think?

Best regards, Ilya Maximets.
Dumitru Ceara Nov. 10, 2020, 10:31 a.m. UTC | #2
On 11/10/20 11:07 AM, Ilya Maximets wrote:
> On 11/9/20 12:09 PM, Dumitru Ceara wrote:
>> IDL clients had no way of checking whether monitor_cond_change requests
>> were pending (either local or in flight).  This commit introduces a new
>> API to check for the state of the conditional monitoring clauses.
>>
>> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
>> ---
>>  lib/ovsdb-idl.c | 40 ++++++++++++++++++++++++++++++++--------
>>  lib/ovsdb-idl.h |  1 +
>>  2 files changed, 33 insertions(+), 8 deletions(-)
>>
> 
> <snip>
> 
>> diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
>> index a1a5776..3f19d40 100644
>> --- a/lib/ovsdb-idl.h
>> +++ b/lib/ovsdb-idl.h
>> @@ -421,6 +421,7 @@ unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *,
>>                                       const struct ovsdb_idl_condition *);
>>  
>>  unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *);
>> +bool ovsdb_idl_monitor_condition_pending(struct ovsdb_idl *);
> 
> I don't think that we need a new api for this.  Condition sequence number,
> I believe, exists for exactly this case.  There is an issue, however, that
> db bindings doesn't return result of ovsdb_idl_set_condition() throwing it
> away without giving a chance for an idl user to actually use it.  That could
> be fixed by something like this:
> 
> diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
> index 698fe25f3..d319adb03 100755
> --- a/ovsdb/ovsdb-idlc.in
> +++ b/ovsdb/ovsdb-idlc.in
> @@ -1416,10 +1416,10 @@ struct %(s)s *
>          print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
>              structName, structName.upper()))
>          print("""
> -void
> +unsigned int
>  %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition)
>  {
> -    ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
> +    return ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
>  }""" % {'p': prefix,
>          's': structName,
>          'tl': tableName.lower()})
> ---
> 
> I think, I had this patch somewhere already, but it seems that I never
> actually send it.

Thanks for looking into this, Ilya!  Yes, returning the seqno would
probably be nice to have in *_set_condition(..).

> 
> With this change ovn-controller will need to store the returned value
> and wait until current condition seqno != expected to be sure that
> condition was successfully set.
> 
> What do you think?
> 

I thought about this too before proposing the new API but it seemed to
me that in that case the code that sets the conditions in ovn-controller
might get unnecessarily complicated:

https://github.com/ovn-org/ovn/blob/c108f23e1c10910031f9409b79001d001aae0c8f/controller/ovn-controller.c#L240

I guess it can be rewritten as something like this:

expected_cond_seqno = 0;
expected_cond_seqno =
    MAX(sbrec_port_binding_set_condition(ovnsb_idl, &pb),
        expected_cond_seqno);
[...]
expected_cond_seqno =
    MAX(sbrec_chassis_private_set_condition(ovnsb_idl, &chprv),
    expected_cond_seqno);
[...]
return expected_cond_seqno;

I know it's not really OVS's problem but the set_condition() API doesn't
seem to make it easy to write simple code to use it properly.

However, if you think a new API would be redundant, we'll have to just
find a way to properly explain (comments I guess) why we need to do
things like this in ovn-controller.

Regards,
Dumitru
Ilya Maximets Nov. 10, 2020, 11:50 a.m. UTC | #3
On 11/10/20 11:31 AM, Dumitru Ceara wrote:
> On 11/10/20 11:07 AM, Ilya Maximets wrote:
>> On 11/9/20 12:09 PM, Dumitru Ceara wrote:
>>> IDL clients had no way of checking whether monitor_cond_change requests
>>> were pending (either local or in flight).  This commit introduces a new
>>> API to check for the state of the conditional monitoring clauses.
>>>
>>> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
>>> ---
>>>  lib/ovsdb-idl.c | 40 ++++++++++++++++++++++++++++++++--------
>>>  lib/ovsdb-idl.h |  1 +
>>>  2 files changed, 33 insertions(+), 8 deletions(-)
>>>
>>
>> <snip>
>>
>>> diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
>>> index a1a5776..3f19d40 100644
>>> --- a/lib/ovsdb-idl.h
>>> +++ b/lib/ovsdb-idl.h
>>> @@ -421,6 +421,7 @@ unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *,
>>>                                       const struct ovsdb_idl_condition *);
>>>  
>>>  unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *);
>>> +bool ovsdb_idl_monitor_condition_pending(struct ovsdb_idl *);
>>
>> I don't think that we need a new api for this.  Condition sequence number,
>> I believe, exists for exactly this case.  There is an issue, however, that
>> db bindings doesn't return result of ovsdb_idl_set_condition() throwing it
>> away without giving a chance for an idl user to actually use it.  That could
>> be fixed by something like this:
>>
>> diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
>> index 698fe25f3..d319adb03 100755
>> --- a/ovsdb/ovsdb-idlc.in
>> +++ b/ovsdb/ovsdb-idlc.in
>> @@ -1416,10 +1416,10 @@ struct %(s)s *
>>          print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
>>              structName, structName.upper()))
>>          print("""
>> -void
>> +unsigned int
>>  %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition)
>>  {
>> -    ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
>> +    return ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
>>  }""" % {'p': prefix,
>>          's': structName,
>>          'tl': tableName.lower()})
>> ---
>>
>> I think, I had this patch somewhere already, but it seems that I never
>> actually send it.
> 
> Thanks for looking into this, Ilya!  Yes, returning the seqno would
> probably be nice to have in *_set_condition(..).
> 
>>
>> With this change ovn-controller will need to store the returned value
>> and wait until current condition seqno != expected to be sure that
>> condition was successfully set.
>>
>> What do you think?
>>
> 
> I thought about this too before proposing the new API but it seemed to
> me that in that case the code that sets the conditions in ovn-controller
> might get unnecessarily complicated:
> 
> https://github.com/ovn-org/ovn/blob/c108f23e1c10910031f9409b79001d001aae0c8f/controller/ovn-controller.c#L240
> 
> I guess it can be rewritten as something like this:
> 
> expected_cond_seqno = 0;
> expected_cond_seqno =
>     MAX(sbrec_port_binding_set_condition(ovnsb_idl, &pb),
>         expected_cond_seqno);
> [...]
> expected_cond_seqno =
>     MAX(sbrec_chassis_private_set_condition(ovnsb_idl, &chprv),
>     expected_cond_seqno);
> [...]
> return expected_cond_seqno;
> 
> I know it's not really OVS's problem but the set_condition() API doesn't
> seem to make it easy to write simple code to use it properly.
> 
> However, if you think a new API would be redundant, we'll have to just
> find a way to properly explain (comments I guess) why we need to do
> things like this in ovn-controller.

Maybe a little pinch of magic will help? :)

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index a06cae3cc..8bc331e95 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -236,16 +236,24 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
         }
     }
 
-out:
-    sbrec_port_binding_set_condition(ovnsb_idl, &pb);
-    sbrec_logical_flow_set_condition(ovnsb_idl, &lf);
-    sbrec_mac_binding_set_condition(ovnsb_idl, &mb);
-    sbrec_multicast_group_set_condition(ovnsb_idl, &mg);
-    sbrec_dns_set_condition(ovnsb_idl, &dns);
-    sbrec_controller_event_set_condition(ovnsb_idl, &ce);
-    sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast);
-    sbrec_igmp_group_set_condition(ovnsb_idl, &igmp);
-    sbrec_chassis_private_set_condition(ovnsb_idl, &chprv);
+out:;
+    unsigned int cond_seqnos[] = {
+        sbrec_port_binding_set_condition(ovnsb_idl, &pb),
+        sbrec_logical_flow_set_condition(ovnsb_idl, &lf),
+        sbrec_mac_binding_set_condition(ovnsb_idl, &mb),
+        sbrec_multicast_group_set_condition(ovnsb_idl, &mg),
+        sbrec_dns_set_condition(ovnsb_idl, &dns),
+        sbrec_controller_event_set_condition(ovnsb_idl, &ce),
+        sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast),
+        sbrec_igmp_group_set_condition(ovnsb_idl, &igmp),
+    };
+    /* We'll need to wait for a maximum expected sequence number to be sure
+     * that all conditions accepted by the server. */
+    unsigned int expected_cond_seqno = 0;
+    for (size_t i = 0; i < ARRAY_SIZE(cond_seqnos); i++) {
+        expected_cond_seqno = MAX(expected_cond_seqno, cond_seqnos[i]);
+    }
+
     ovsdb_idl_condition_destroy(&pb);
     ovsdb_idl_condition_destroy(&lf);
     ovsdb_idl_condition_destroy(&mb);
@@ -255,6 +263,8 @@ out:
     ovsdb_idl_condition_destroy(&ip_mcast);
     ovsdb_idl_condition_destroy(&igmp);
     ovsdb_idl_condition_destroy(&chprv);
+
+    return expected_cond_seqno;
 }
 
 static const char *
---

Best regards, Ilya Maximets.
Dumitru Ceara Nov. 10, 2020, 11:59 a.m. UTC | #4
On 11/10/20 12:50 PM, Ilya Maximets wrote:
> On 11/10/20 11:31 AM, Dumitru Ceara wrote:
>> On 11/10/20 11:07 AM, Ilya Maximets wrote:
>>> On 11/9/20 12:09 PM, Dumitru Ceara wrote:
>>>> IDL clients had no way of checking whether monitor_cond_change requests
>>>> were pending (either local or in flight).  This commit introduces a new
>>>> API to check for the state of the conditional monitoring clauses.
>>>>
>>>> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
>>>> ---
>>>>  lib/ovsdb-idl.c | 40 ++++++++++++++++++++++++++++++++--------
>>>>  lib/ovsdb-idl.h |  1 +
>>>>  2 files changed, 33 insertions(+), 8 deletions(-)
>>>>
>>>
>>> <snip>
>>>
>>>> diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
>>>> index a1a5776..3f19d40 100644
>>>> --- a/lib/ovsdb-idl.h
>>>> +++ b/lib/ovsdb-idl.h
>>>> @@ -421,6 +421,7 @@ unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *,
>>>>                                       const struct ovsdb_idl_condition *);
>>>>  
>>>>  unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *);
>>>> +bool ovsdb_idl_monitor_condition_pending(struct ovsdb_idl *);
>>>
>>> I don't think that we need a new api for this.  Condition sequence number,
>>> I believe, exists for exactly this case.  There is an issue, however, that
>>> db bindings doesn't return result of ovsdb_idl_set_condition() throwing it
>>> away without giving a chance for an idl user to actually use it.  That could
>>> be fixed by something like this:
>>>
>>> diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
>>> index 698fe25f3..d319adb03 100755
>>> --- a/ovsdb/ovsdb-idlc.in
>>> +++ b/ovsdb/ovsdb-idlc.in
>>> @@ -1416,10 +1416,10 @@ struct %(s)s *
>>>          print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
>>>              structName, structName.upper()))
>>>          print("""
>>> -void
>>> +unsigned int
>>>  %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition)
>>>  {
>>> -    ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
>>> +    return ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
>>>  }""" % {'p': prefix,
>>>          's': structName,
>>>          'tl': tableName.lower()})
>>> ---
>>>
>>> I think, I had this patch somewhere already, but it seems that I never
>>> actually send it.
>>
>> Thanks for looking into this, Ilya!  Yes, returning the seqno would
>> probably be nice to have in *_set_condition(..).
>>
>>>
>>> With this change ovn-controller will need to store the returned value
>>> and wait until current condition seqno != expected to be sure that
>>> condition was successfully set.
>>>
>>> What do you think?
>>>
>>
>> I thought about this too before proposing the new API but it seemed to
>> me that in that case the code that sets the conditions in ovn-controller
>> might get unnecessarily complicated:
>>
>> https://github.com/ovn-org/ovn/blob/c108f23e1c10910031f9409b79001d001aae0c8f/controller/ovn-controller.c#L240
>>
>> I guess it can be rewritten as something like this:
>>
>> expected_cond_seqno = 0;
>> expected_cond_seqno =
>>     MAX(sbrec_port_binding_set_condition(ovnsb_idl, &pb),
>>         expected_cond_seqno);
>> [...]
>> expected_cond_seqno =
>>     MAX(sbrec_chassis_private_set_condition(ovnsb_idl, &chprv),
>>     expected_cond_seqno);
>> [...]
>> return expected_cond_seqno;
>>
>> I know it's not really OVS's problem but the set_condition() API doesn't
>> seem to make it easy to write simple code to use it properly.
>>
>> However, if you think a new API would be redundant, we'll have to just
>> find a way to properly explain (comments I guess) why we need to do
>> things like this in ovn-controller.
> 
> Maybe a little pinch of magic will help? :)
> 

I think it does. :)

> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index a06cae3cc..8bc331e95 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -236,16 +236,24 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
>          }
>      }
>  
> -out:
> -    sbrec_port_binding_set_condition(ovnsb_idl, &pb);
> -    sbrec_logical_flow_set_condition(ovnsb_idl, &lf);
> -    sbrec_mac_binding_set_condition(ovnsb_idl, &mb);
> -    sbrec_multicast_group_set_condition(ovnsb_idl, &mg);
> -    sbrec_dns_set_condition(ovnsb_idl, &dns);
> -    sbrec_controller_event_set_condition(ovnsb_idl, &ce);
> -    sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast);
> -    sbrec_igmp_group_set_condition(ovnsb_idl, &igmp);
> -    sbrec_chassis_private_set_condition(ovnsb_idl, &chprv);
> +out:;

I'll see if I can get rid of this label all together.

> +    unsigned int cond_seqnos[] = {
> +        sbrec_port_binding_set_condition(ovnsb_idl, &pb),
> +        sbrec_logical_flow_set_condition(ovnsb_idl, &lf),
> +        sbrec_mac_binding_set_condition(ovnsb_idl, &mb),
> +        sbrec_multicast_group_set_condition(ovnsb_idl, &mg),
> +        sbrec_dns_set_condition(ovnsb_idl, &dns),
> +        sbrec_controller_event_set_condition(ovnsb_idl, &ce),
> +        sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast),
> +        sbrec_igmp_group_set_condition(ovnsb_idl, &igmp),
> +    };
> +    /* We'll need to wait for a maximum expected sequence number to be sure
> +     * that all conditions accepted by the server. */
> +    unsigned int expected_cond_seqno = 0;
> +    for (size_t i = 0; i < ARRAY_SIZE(cond_seqnos); i++) {
> +        expected_cond_seqno = MAX(expected_cond_seqno, cond_seqnos[i]);
> +    }
> +
>      ovsdb_idl_condition_destroy(&pb);
>      ovsdb_idl_condition_destroy(&lf);
>      ovsdb_idl_condition_destroy(&mb);
> @@ -255,6 +263,8 @@ out:
>      ovsdb_idl_condition_destroy(&ip_mcast);
>      ovsdb_idl_condition_destroy(&igmp);
>      ovsdb_idl_condition_destroy(&chprv);
> +
> +    return expected_cond_seqno;
>  }
>  
>  static const char *

Will you be sending a patch for ovsdb-idlc.in to expose the expected seqno?

Thanks,
Dumitru
Ilya Maximets Nov. 10, 2020, 12:20 p.m. UTC | #5
On 11/10/20 12:59 PM, Dumitru Ceara wrote:
> On 11/10/20 12:50 PM, Ilya Maximets wrote:
>> On 11/10/20 11:31 AM, Dumitru Ceara wrote:
>>> On 11/10/20 11:07 AM, Ilya Maximets wrote:
>>>> On 11/9/20 12:09 PM, Dumitru Ceara wrote:
>>>>> IDL clients had no way of checking whether monitor_cond_change requests
>>>>> were pending (either local or in flight).  This commit introduces a new
>>>>> API to check for the state of the conditional monitoring clauses.
>>>>>
>>>>> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
>>>>> ---
>>>>>  lib/ovsdb-idl.c | 40 ++++++++++++++++++++++++++++++++--------
>>>>>  lib/ovsdb-idl.h |  1 +
>>>>>  2 files changed, 33 insertions(+), 8 deletions(-)
>>>>>
>>>>
>>>> <snip>
>>>>
>>>>> diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
>>>>> index a1a5776..3f19d40 100644
>>>>> --- a/lib/ovsdb-idl.h
>>>>> +++ b/lib/ovsdb-idl.h
>>>>> @@ -421,6 +421,7 @@ unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *,
>>>>>                                       const struct ovsdb_idl_condition *);
>>>>>  
>>>>>  unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *);
>>>>> +bool ovsdb_idl_monitor_condition_pending(struct ovsdb_idl *);
>>>>
>>>> I don't think that we need a new api for this.  Condition sequence number,
>>>> I believe, exists for exactly this case.  There is an issue, however, that
>>>> db bindings doesn't return result of ovsdb_idl_set_condition() throwing it
>>>> away without giving a chance for an idl user to actually use it.  That could
>>>> be fixed by something like this:
>>>>
>>>> diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
>>>> index 698fe25f3..d319adb03 100755
>>>> --- a/ovsdb/ovsdb-idlc.in
>>>> +++ b/ovsdb/ovsdb-idlc.in
>>>> @@ -1416,10 +1416,10 @@ struct %(s)s *
>>>>          print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
>>>>              structName, structName.upper()))
>>>>          print("""
>>>> -void
>>>> +unsigned int
>>>>  %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition)
>>>>  {
>>>> -    ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
>>>> +    return ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
>>>>  }""" % {'p': prefix,
>>>>          's': structName,
>>>>          'tl': tableName.lower()})
>>>> ---
>>>>
>>>> I think, I had this patch somewhere already, but it seems that I never
>>>> actually send it.
>>>
>>> Thanks for looking into this, Ilya!  Yes, returning the seqno would
>>> probably be nice to have in *_set_condition(..).
>>>
>>>>
>>>> With this change ovn-controller will need to store the returned value
>>>> and wait until current condition seqno != expected to be sure that
>>>> condition was successfully set.
>>>>
>>>> What do you think?
>>>>
>>>
>>> I thought about this too before proposing the new API but it seemed to
>>> me that in that case the code that sets the conditions in ovn-controller
>>> might get unnecessarily complicated:
>>>
>>> https://github.com/ovn-org/ovn/blob/c108f23e1c10910031f9409b79001d001aae0c8f/controller/ovn-controller.c#L240
>>>
>>> I guess it can be rewritten as something like this:
>>>
>>> expected_cond_seqno = 0;
>>> expected_cond_seqno =
>>>     MAX(sbrec_port_binding_set_condition(ovnsb_idl, &pb),
>>>         expected_cond_seqno);
>>> [...]
>>> expected_cond_seqno =
>>>     MAX(sbrec_chassis_private_set_condition(ovnsb_idl, &chprv),
>>>     expected_cond_seqno);
>>> [...]
>>> return expected_cond_seqno;
>>>
>>> I know it's not really OVS's problem but the set_condition() API doesn't
>>> seem to make it easy to write simple code to use it properly.
>>>
>>> However, if you think a new API would be redundant, we'll have to just
>>> find a way to properly explain (comments I guess) why we need to do
>>> things like this in ovn-controller.
>>
>> Maybe a little pinch of magic will help? :)
>>
> 
> I think it does. :)
> 
>> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
>> index a06cae3cc..8bc331e95 100644
>> --- a/controller/ovn-controller.c
>> +++ b/controller/ovn-controller.c
>> @@ -236,16 +236,24 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
>>          }
>>      }
>>  
>> -out:
>> -    sbrec_port_binding_set_condition(ovnsb_idl, &pb);
>> -    sbrec_logical_flow_set_condition(ovnsb_idl, &lf);
>> -    sbrec_mac_binding_set_condition(ovnsb_idl, &mb);
>> -    sbrec_multicast_group_set_condition(ovnsb_idl, &mg);
>> -    sbrec_dns_set_condition(ovnsb_idl, &dns);
>> -    sbrec_controller_event_set_condition(ovnsb_idl, &ce);
>> -    sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast);
>> -    sbrec_igmp_group_set_condition(ovnsb_idl, &igmp);
>> -    sbrec_chassis_private_set_condition(ovnsb_idl, &chprv);
>> +out:;
> 
> I'll see if I can get rid of this label all together.
> 
>> +    unsigned int cond_seqnos[] = {
>> +        sbrec_port_binding_set_condition(ovnsb_idl, &pb),
>> +        sbrec_logical_flow_set_condition(ovnsb_idl, &lf),
>> +        sbrec_mac_binding_set_condition(ovnsb_idl, &mb),
>> +        sbrec_multicast_group_set_condition(ovnsb_idl, &mg),
>> +        sbrec_dns_set_condition(ovnsb_idl, &dns),
>> +        sbrec_controller_event_set_condition(ovnsb_idl, &ce),
>> +        sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast),
>> +        sbrec_igmp_group_set_condition(ovnsb_idl, &igmp),
>> +    };
>> +    /* We'll need to wait for a maximum expected sequence number to be sure
>> +     * that all conditions accepted by the server. */
>> +    unsigned int expected_cond_seqno = 0;
>> +    for (size_t i = 0; i < ARRAY_SIZE(cond_seqnos); i++) {
>> +        expected_cond_seqno = MAX(expected_cond_seqno, cond_seqnos[i]);
>> +    }
>> +
>>      ovsdb_idl_condition_destroy(&pb);
>>      ovsdb_idl_condition_destroy(&lf);
>>      ovsdb_idl_condition_destroy(&mb);
>> @@ -255,6 +263,8 @@ out:
>>      ovsdb_idl_condition_destroy(&ip_mcast);
>>      ovsdb_idl_condition_destroy(&igmp);
>>      ovsdb_idl_condition_destroy(&chprv);
>> +
>> +    return expected_cond_seqno;
>>  }
>>  
>>  static const char *
> 
> Will you be sending a patch for ovsdb-idlc.in to expose the expected seqno?

Sent:
  https://patchwork.ozlabs.org/project/openvswitch/patch/20201110121811.2205350-1-i.maximets@ovn.org/

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index fdb9d85..8c0f86c 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -188,6 +188,17 @@  enum ovsdb_idl_monitoring {
                                          outstanding. */
 };
 
+enum ovsdb_idl_monitor_cond_state {
+    OVSDB_IDL_MONITOR_COND_ACKED,     /* Local conditional monitoring clauses
+                                       * have been acked by the server. */
+    OVSDB_IDL_MONITOR_COND_LOCAL,     /* Local conditional monitoring clause
+                                       * changes have not yet been sent to the
+                                       * server. */
+    OVSDB_IDL_MONITOR_COND_REQUESTED, /* Local conditional monitoring clause
+                                       * changes have been sent to the server
+                                       * but have not yet been acked. */
+};
+
 struct ovsdb_idl_db {
     struct ovsdb_idl *idl;
 
@@ -203,8 +214,8 @@  struct ovsdb_idl_db {
     struct json *schema;
     enum ovsdb_idl_monitoring monitoring;
 
-    /* True if any of the tables' monitoring conditions has changed. */
-    bool cond_changed;
+    /* Current state of the conditional monitoring clauses. */
+    enum ovsdb_idl_monitor_cond_state cond_state;
 
     unsigned int cond_seqno;   /* Keep track of condition clauses changes
                                   over a single conditional monitoring session.
@@ -1580,7 +1591,7 @@  ovsdb_idl_db_set_condition(struct ovsdb_idl_db *db,
 
     if (!ovsdb_idl_condition_equals(condition, table_cond)) {
         ovsdb_idl_condition_clone(&table->new_cond, condition);
-        db->cond_changed = true;
+        db->cond_state = OVSDB_IDL_MONITOR_COND_LOCAL;
         poll_immediate_wake();
         return seqno + 1;
     }
@@ -1638,7 +1649,7 @@  ovsdb_idl_create_cond_change_req(const struct ovsdb_idl_condition *cond)
 static struct jsonrpc_msg *
 ovsdb_idl_db_compose_cond_change(struct ovsdb_idl_db *db)
 {
-    if (!db->cond_changed) {
+    if (db->cond_state != OVSDB_IDL_MONITOR_COND_LOCAL) {
         return NULL;
     }
 
@@ -1672,7 +1683,7 @@  ovsdb_idl_db_compose_cond_change(struct ovsdb_idl_db *db)
         return NULL;
     }
 
-    db->cond_changed = false;
+    db->cond_state = OVSDB_IDL_MONITOR_COND_REQUESTED;
     struct json *params = json_array_create_3(json_clone(db->monitor_id),
                                               json_clone(db->monitor_id),
                                               monitor_cond_change_requests);
@@ -1693,6 +1704,19 @@  ovsdb_idl_db_ack_condition(struct ovsdb_idl_db *db)
             ovsdb_idl_condition_move(&table->ack_cond, &table->req_cond);
         }
     }
+
+    /* Ack the last monitor condition change if no local changes happened in
+     * the meantime.
+     */
+    if (db->cond_state == OVSDB_IDL_MONITOR_COND_REQUESTED) {
+        db->cond_state = OVSDB_IDL_MONITOR_COND_ACKED;
+    }
+}
+
+bool
+ovsdb_idl_monitor_condition_pending(struct ovsdb_idl *idl)
+{
+    return idl->data.cond_state != OVSDB_IDL_MONITOR_COND_ACKED;
 }
 
 /* Should be called when the IDL fsm is restarted and resyncs table conditions
@@ -1712,7 +1736,7 @@  ovsdb_idl_db_sync_condition(struct ovsdb_idl_db *db)
 {
     bool ack_all = uuid_is_zero(&db->last_id);
 
-    db->cond_changed = false;
+    db->cond_state = OVSDB_IDL_MONITOR_COND_ACKED;
     for (size_t i = 0; i < db->class_->n_tables; i++) {
         struct ovsdb_idl_table *table = &db->tables[i];
 
@@ -1731,7 +1755,7 @@  ovsdb_idl_db_sync_condition(struct ovsdb_idl_db *db)
         } else {
             /* If there was no "unsent" condition but instead a
              * monitor_cond_change request was in flight, move table->req_cond
-             * to table->new_cond and set db->cond_changed to trigger a new
+             * to table->new_cond and set db->cond_state to trigger a new
              * monitor_cond_change request.
              *
              * However, if a new condition has been set by the IDL client,
@@ -1740,7 +1764,7 @@  ovsdb_idl_db_sync_condition(struct ovsdb_idl_db *db)
              */
             if (table->req_cond && !table->new_cond) {
                 ovsdb_idl_condition_move(&table->new_cond, &table->req_cond);
-                db->cond_changed = true;
+                db->cond_state = OVSDB_IDL_MONITOR_COND_LOCAL;
             }
         }
     }
diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
index a1a5776..3f19d40 100644
--- a/lib/ovsdb-idl.h
+++ b/lib/ovsdb-idl.h
@@ -421,6 +421,7 @@  unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *,
                                      const struct ovsdb_idl_condition *);
 
 unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *);
+bool ovsdb_idl_monitor_condition_pending(struct ovsdb_idl *);
 
 /* Indexes over one or more columns in the IDL, to retrieve rows matching
  * particular search criteria and to iterate over a subset of rows in a defined