On 28.04.2017 15:32, Bala Manoharan wrote:
> On 28 April 2017 at 15:41, Dmitry Eremin-Solenikov
> <dmitry.ereminsoleni...@linaro.org> wrote:
>> On 28.04.2017 12:27, Peltonen, Janne (Nokia - FI/Espoo) wrote:
>>> Hi,
>>>
>>>> -----Original Message-----
>>>> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of 
>>>> Dmitry Eremin-
>>>> Solenikov
>>>> Sent: Friday, April 28, 2017 11:59 AM
>>>> To: lng-odp-forward <lng-odp@lists.linaro.org>
>>>> Subject: [lng-odp] IPsec SA disabling
>>>>
>>>> Hello,
>>>>
>>>> While responding to Janne's email, I've come to an issue which warrants
>>>> a separate discussion IMO.
>>>>
>>>> Consider the following scenario. Application with two thread.
>>>>
>>>> - First thread: gets outbound packet, finds SA through SPD, configures
>>>> IPsec request, submits it.
>>>>
>>>> - Second thread: wants to disable SA, pending deletion.
>>>>
>>>> Is that an application error if SA was disabled after being looked up,
>>>> but before being submitted by another thread? Yes it is.
>>>
>>> Yes, it would be an error.
>>>
>>>> Right now SA
>>>> disabling/deletion is susceptible to race conditions. It requires an app
>>>> to lock SA after lookup, unlock it after submission, etc.
>>>
>>> To avoid races one indeed currently needs some synchronization in the
>>> application side. Not necessarily locks but something.
>>>
>>> The OFP IPsec draft code (which is just draft, trying to use the ODP API),
>>> refcounts SA usage and disables an SA only after it has been removed
>>> from the SAD and after ongoing operations (tracked through the refcount)
>>> have completed.
>>
>> Basically as we already have refcounting on ODP side, I'd suggest
>> reusing it in applications.
>>
>>>
>>> Because of the above, one could wonder why even have disable() in the
>>> API. The main reason is to be able to disable offloaded inbound SA
>>> lookup for the SA so that the SA can be safely deleted (the application
>>> needs to be able to clean up its own SA state but cannot do it if there
>>> are in-flight inbound operations that may still refer (through the ctx ptr)
>>> to the application SA state).
>>
>> How do you track references of SA instances returned from ODP after
>> lookup? How will application cope with disabling/deleting SA if it is
>> returned to another thread by ODP?
>>
>>>
>>>> Should ODP
>>>> provide API to 'lock' SA?
>>>
>>> It would be convenient to the application if disable() could be called
>>> at any time. But that could impose difficult synchronization needs
>>> in the ODP implementation side and therefore we thought that it is
>>> better to leave that to the application which may need to do some
>>> synchronization anyway due to its own needs.
>>>
>>> But this is definitely a good topic to ponder about. It is possible
>>> that the current API got this wrong, but it is not easy to see how
>>> things should be if they need to be changed.
>>
>> Well, right now there is a need to do synchronization on ODP side
>> because odp_ipsec_sa_disable() is not an optional call.
>>
>>>> I was thinking about smth like:
>>>>
>>>> int odp_ipsec_sa_use(odp_ipsec_sa_t sa);
>>>>
>>>> void odp_ipsec_sa_unuse(odp_ipsec_sa_t sa);
>>>>
>>>> One would use first function when an app has looked up SA in it's own
>>>> tables and is going to submit it via one of odp_ipsec_* processing calls
>>>> (except or including SA deletion/disabling -- TBD).
>>>
>>> I am not sure how this would help and be better than something done
>>> totally at the application side. This would anyway require a bit more
>>> specification to define the semantics. For instance, when unuse() could
>>> be called with respect to the enque operations and what exactly it
>>> would mean.
>>
>> I'm just suggesting to move reference counting from application to ODP
>> side, since ODP has to do refcounting anyway (_disable() should wait
>> till all currently running operations with this SA finish).
>>
>> I thought basic refounting in mind. Probably we can get this as easy as:
>>
>> - odp_ipsec_sa_create:
>>
>>   Create SA with refcnt = 1
>>
>> - App looks up SA in SAD
>>   odp_ipsec_sa_use(sa)
>>
>> - App has looked up SA in SAD, but then changed its mind
>>   odp_ipsec_sa_unuse(sa)
>>
>> - ODP looks up SA in cache (via a request from app or via inline inbound
>> operation
>>   odp_ipsec_sa_use(sa)
>>
>> - Application receives SA via a return from IPsec.
>>   - Processes it and then calls odp_ipsec_sa_unuse().
>>
>> - Application wants to disable SA in ASYNC mode.
>>   odp_ipsec_sa_disable() marks SA for disablement.
>>   - ASYNC case. It calls ipsec_sa_unuse() then returns.
>>
>>   - SYNC case. It waits for refcount to drop to 1, unuses it then
>> returns.
>>   - OR(!) SYNC case. It calls ipsec_sa_unuse(), waits for refcount to
>> drop to 0, then reutrns.
>>
>> - odp_ipsec_sa_unuse() is called with refount becoming 0.
>>   - ASYNC case:
>>     submit an even.
>>
>>   - SYNC case:
>>     do nothing.
> 
> I believe this synchronisation at application end might not be too
> difficult for look-aside mode since SA create/delete call is part of
> control flow and ipsec lookup is part of the data flow.

Even for lookaside mode synchronization is required since ODP can lookup
SA from inbound packet asynchronously with main app.

> In case of inline mode when application calls odp_ipsec_sa_disable()
> the SA gets disabled but there could be few transient packets which
> might flow during disable operation and when application calls
> odp_ipsec_sa_destroy() the destroy operation could simply fail if
> there are few packets which are still processed then the application
> could call the odp_ipsec_sa_destroy() after sometime when it becomes
> success.

This would require additional checks in ODP side. Also if currently
sa_destroy() can be called from event handler, completely destroying SA,
with your suggestion it is unclear when sa_destroy() can be called.
Especially if first call fails.

-- 
With best wishes
Dmitry

Reply via email to